<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/M.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/M.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/M.png">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"maureen-liu.gitee.io","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null,"activeClass":"valine"},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="C++ Standard Template Library and Generic Programming  前言 所谓Generic Programming（GP，泛型编程），就是使用 template（模板）为主要工具来编写程序。本课程第二讲开宗明义阐述了 GP 与 OOP（Object Oriented Programming）的根本差异，并谈及 templates 的意义和运用。 制作本讲">
<meta property="og:type" content="article">
<meta property="og:title" content="C++STL标准库与泛型编程">
<meta property="og:url" content="https://maureen-liu.gitee.io/p/ae8b63c8.html">
<meta property="og:site_name" content="Maureen&#39;s blog">
<meta property="og:description" content="C++ Standard Template Library and Generic Programming  前言 所谓Generic Programming（GP，泛型编程），就是使用 template（模板）为主要工具来编写程序。本课程第二讲开宗明义阐述了 GP 与 OOP（Object Oriented Programming）的根本差异，并谈及 templates 的意义和运用。 制作本讲">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173346903.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173414062.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173527017.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173612979.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173643756.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173710379.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173840767.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173912730.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173947034.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174022009.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174051961.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174112655.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174129065.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174140679.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174159013.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174223453.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174242385.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174258174.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174312382.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174327487.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174342659.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174357857.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174538135.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174617363.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174628571.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174709030.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174727606.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174741620.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174804143.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174816521.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174844564.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174910651.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174927488.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174942175.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170424184.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170541698.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170608518.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170629180.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170724688.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170743188.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170849235.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170905933.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171159604.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171217055.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171327289.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171355498.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171421293.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171443931.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171538209.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171552900.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171606981.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171636483.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171746758.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171816435.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171835762.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171900497.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171913193.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172016648.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172005073.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172032944.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172104403.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172052689.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172142223.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172246005.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172300440.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172215059.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172658562.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172725770.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172747899.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172817767.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172833959.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172940210.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173005100.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173043306.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173113966.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173140798.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173207147.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173227595.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173351711.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173412378.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173425324.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173449114.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173524053.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173605425.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173620723.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173650236.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173701515.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173727443.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173749834.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173817837.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173842824.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173919849.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173935419.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173958490.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174013620.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174025553.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174046616.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174128722.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174149104.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174231839.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174255541.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174332980.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174346490.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174359305.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174526646.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174546788.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174608781.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174628938.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174759972.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174714367.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174728444.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174824878.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174840212.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174903260.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174935649.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175007999.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175024027.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175043995.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175103875.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175129044.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175148989.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175206845.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175221195.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175310483.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175326136.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175355949.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175423626.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175442749.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175456957.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175516300.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175543473.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175621996.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175640216.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175650302.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175711678.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175735873.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181041775.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181107336.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181141617.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181201178.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181237405.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181318976.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181355615.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181418127.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181431735.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181450241.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181510827.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181538549.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229145848368.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229150638951.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229150916241.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229151933041.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229152431896.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160700965.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160726888.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160747760.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160817462.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160848023.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160913555.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160927785.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160938732.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161009970.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161026819.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161041373.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161055262.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161148961.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161205170.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161217409.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161239736.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161256258.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161314306.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171153305.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171211012.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171224902.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171237136.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171255402.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132010313.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132045090.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132643551.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132708298.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010219672.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010252815.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010319608.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010354017.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010420319.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010653691.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010717974.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010807126.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011102123.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011209379.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011330517.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011400517.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011436556.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011501814.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011521657.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011537389.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011559124.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011615400.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011629785.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011643134.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011656143.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011711668.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011726355.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011745981.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011759241.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011812065.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011827090.png">
<meta property="article:published_time" content="2021-12-21T09:26:46.000Z">
<meta property="article:modified_time" content="2022-01-03T11:47:22.119Z">
<meta property="article:author" content="Maureen">
<meta property="article:tag" content="侯捷">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173346903.png">

<link rel="canonical" href="https://maureen-liu.gitee.io/p/ae8b63c8.html">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>
<script src="/lib/fireworks.js"></script>
  <title>C++STL标准库与泛型编程 | Maureen's blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Maureen's blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">记录学习的点点滴滴</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://maureen-liu.gitee.io/p/ae8b63c8.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/stan.jpeg">
      <meta itemprop="name" content="Maureen">
      <meta itemprop="description" content="心之所向，素履以往">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Maureen's blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          C++STL标准库与泛型编程
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-12-21 17:26:46" itemprop="dateCreated datePublished" datetime="2021-12-21T17:26:46+08:00">2021-12-21</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-01-03 19:47:22" itemprop="dateModified" datetime="2022-01-03T19:47:22+08:00">2022-01-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/C/" itemprop="url" rel="index"><span itemprop="name">C++</span></a>
                </span>
                  ，
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/C/STL/" itemprop="url" rel="index"><span itemprop="name">STL</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/p/ae8b63c8.html#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/p/ae8b63c8.html" itemprop="commentCount"></span>
    </a>
  </span>
  
  <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>90k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>1:22</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
      
      
        <p>C++ Standard Template Library and Generic Programming</p>
<h1 id="前言"><a class="markdownIt-Anchor" href="#前言"></a> 前言</h1>
<p>所谓Generic Programming（GP，泛型编程），就是使用 template（模板）为主要工具来编写程序。本课程第二讲开宗明义阐述了 GP 与 OOP（Object Oriented Programming）的根本差异，并谈及 templates 的意义和运用。</p>
<p>制作本讲义时，我使用的题目是《C<ins>标准库 — 体系结构与内核分析》（C</ins> Standard Library —— architecture &amp; sources)；由于本课程之最精髓就是根据源代码分析 C++ STL 之体系结构，而 STL 正是泛型编程（GP) 最成功的作品，所以本课程事实上就是以 STL 为目标的深层次地探讨泛型编程。</p>
<span id="more"></span>
<h1 id="第一讲"><a class="markdownIt-Anchor" href="#第一讲"></a> 第一讲</h1>
<h2 id="认识headers-版本-重要资源"><a class="markdownIt-Anchor" href="#认识headers-版本-重要资源"></a> 认识headers、版本、重要资源</h2>
<p>C++标准库之体系结构与内核分析</p>
<h3 id="应该具备的基础"><a class="markdownIt-Anchor" href="#应该具备的基础"></a> 应该具备的基础</h3>
<ul>
<li>C++基本语法 （包括如何正确使用<strong>模板，templates</strong>）</li>
</ul>
<h3 id="我们的目标"><a class="markdownIt-Anchor" href="#我们的目标"></a> 我们的目标</h3>
<ul>
<li>level 0：使用C++标准库</li>
<li>level 1：认识C++标准库<sub>（胸中自有丘壑）</sub></li>
<li>level 2：<strong>良好</strong>使用C++标准库</li>
<li>level 3：扩充C++标准库</li>
</ul>
<h3 id="c-standard-library-vs-standard-template-library"><a class="markdownIt-Anchor" href="#c-standard-library-vs-standard-template-library"></a> <strong>C++ Standard Library</strong> vs. <strong>Standard Template Library</strong></h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173346903.png" alt="image-20211221173346903"></p>
<h3 id="c标准库版本"><a class="markdownIt-Anchor" href="#c标准库版本"></a> C++标准库，版本</h3>
<p>不同平台的编译器的版本不影响标准库的用法</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173414062.png" alt="image-20211221173414062"></p>
<h3 id="重要网页"><a class="markdownIt-Anchor" href="#重要网页"></a> 重要网页</h3>
<ul>
<li>
<p><a target="_blank" rel="noopener" href="http://CPlusPlus.com">CPlusPlus.com</a></p>
</li>
<li>
<p><a target="_blank" rel="noopener" href="http://CppReference.com">CppReference.com</a></p>
</li>
<li>
<p><a target="_blank" rel="noopener" href="http://gcc.gnu.org">gcc.gnu.org</a></p>
</li>
</ul>
<h3 id="书籍"><a class="markdownIt-Anchor" href="#书籍"></a> 书籍</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173527017.png" alt="image-20211221173527017"></p>
<h2 id="stl体系结构基础介绍"><a class="markdownIt-Anchor" href="#stl体系结构基础介绍"></a> STL体系结构基础介绍</h2>
<h3 id="stl六大部件"><a class="markdownIt-Anchor" href="#stl六大部件"></a> STL六大部件</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173612979.png" alt="image-20211221173612979"></p>
<p>数据放在“容器”中，需要分配内存存放数据，所以容器的背后是“分配器”，处理数据的操作是“算法”，“算法”和“容器”之间的桥梁是“迭代器”（泛化的指针），有了桥梁，算法才能拿到容器中的数据进行处理。</p>
<h3 id="stl-六大部件关系"><a class="markdownIt-Anchor" href="#stl-六大部件关系"></a> STL 六大部件关系</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173643756.png" alt="image-20211221173643756"></p>
<p><code>count_if(vi.begin(), vi.end(), not1(bind2nd(less&lt;int&gt;(), 40)));</code> 计算容器中大于等于40的数的个数。</p>
<h3 id="复杂度complexitybig-oh"><a class="markdownIt-Anchor" href="#复杂度complexitybig-oh"></a> 复杂度，Complexity，Big-oh</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173710379.png" alt="image-20211221173710379"></p>
<h3 id="前闭后开区间"><a class="markdownIt-Anchor" href="#前闭后开区间"></a> “前闭后开”区间</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173840767.png" alt="image-20211221173840767"></p>
<p>“前闭后开”的意思是容器的范围，<code>begin()</code>指的是第一个元素，<code>end()</code>指的是容器的最后一个元素的下一个位置。</p>
<p>图中的灰色空间不是容器中的数据。</p>
<h3 id="range-based-for-statement-since-c11"><a class="markdownIt-Anchor" href="#range-based-for-statement-since-c11"></a> range-based <em>for</em> statement (since C++11)</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173912730.png" alt="image-20211221173912730"></p>
<p>用 <code>auto&amp;</code> 会将容器中的元素的值进行修改。</p>
<h3 id="auto-keyword-since-c11"><a class="markdownIt-Anchor" href="#auto-keyword-since-c11"></a> <em>auto</em> keyword (since C++11)</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221173947034.png" alt="image-20211221173947034"></p>
<h2 id="容器的分类与各种测试"><a class="markdownIt-Anchor" href="#容器的分类与各种测试"></a> 容器的分类与各种测试</h2>
<h3 id="容器-结构与分类"><a class="markdownIt-Anchor" href="#容器-结构与分类"></a> 容器 — 结构与分类</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174022009.png" alt="image-20211221174022009"></p>
<p>容器主要分为两类：序列式容器和关联式容器。</p>
<p>在C++11之后出现了新的分类 Unordered Containers，也是一种关联式容器。</p>
<p>关联式容器就是key-value，利用key能很快找到value，关联式容器适合做快速查找。</p>
<ul>
<li>
<p>Sequence Containers ：按照放入的次序排列</p>
<ul>
<li>Array：前后都是固定的，不可扩充。</li>
<li>Vector：起点固定，后面可以扩充，放入元素的时候，当空间不够的时候，会自动增长，容器背后的分配器会自动帮其处理内存的事情。</li>
<li>Deque：两端都可进出，前后都可以扩充。</li>
<li>List：标准库中的链表是个双向链表。如果选用List，耗用的内存一定是比Forward-list多的，因为每个元素带两个指针，而Forward-list每个元素带1个指针。</li>
<li>Forward-list：单向链表。图中Forward-list下面的他图也表示单向链表，更加形象，标明了开始的位置。</li>
</ul>
</li>
<li>
<p>Associative Containers：标准库内部并没有规定用什么数据结构来实现，但是由于红黑树的查找效率很高，所以各家编译器所带的标准库都用<em>红黑树</em>实现Set和Map。</p>
<ul>
<li>Set：没有key和value之分，存放的元素不能重复；</li>
<li>Multiset：没有key和value之分，存放的元素可以重复；</li>
<li>Map：每个节点都有key和value，元素的key不能重复；</li>
<li>Multimap：每个节点都有key和value，元素的key可以重复。</li>
</ul>
</li>
<li>
<p>Unordered Containers：使用图中所示的<em>HashTable</em>实现，每条链表不能太长，查找效率低，太长就要打散再进行哈希操作</p>
<ul>
<li>Unordered Set/Multiset</li>
<li>Unordered Map/Multimap</li>
</ul>
</li>
</ul>
<h3 id="以下测试程序之辅助函数"><a class="markdownIt-Anchor" href="#以下测试程序之辅助函数"></a> 以下测试程序之<strong>辅助函数</strong></h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174051961.png" alt="image-20211221174051961"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">long</span> <span class="title">get_a_target_long</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">long</span> target=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;target (0~&quot;</span> &lt;&lt; RAND_MAX &lt;&lt; <span class="string">&quot;): &quot;</span>;</span><br><span class="line">	cin &gt;&gt; target;</span><br><span class="line">	<span class="keyword">return</span> target;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">string <span class="title">get_a_target_string</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">long</span> target=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;target (0~&quot;</span> &lt;&lt; RAND_MAX &lt;&lt; <span class="string">&quot;): &quot;</span>;</span><br><span class="line">	cin &gt;&gt; target;</span><br><span class="line">	<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, target); <span class="comment">//将target转换为字符串</span></span><br><span class="line">	<span class="keyword">return</span> <span class="built_in">string</span>(buf);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">compareLongs</span><span class="params">(<span class="keyword">const</span> <span class="keyword">void</span>* a, <span class="keyword">const</span> <span class="keyword">void</span>* b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">return</span> ( *(<span class="keyword">long</span>*)a - *(<span class="keyword">long</span>*)b );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">compareStrings</span><span class="params">(<span class="keyword">const</span> <span class="keyword">void</span>* a, <span class="keyword">const</span> <span class="keyword">void</span>* b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">if</span> ( *(string*)a &gt; *(string*)b )</span><br><span class="line">     	<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">  <span class="keyword">else</span> <span class="keyword">if</span> ( *(string*)a &lt; *(string*)b )</span><br><span class="line">     	<span class="keyword">return</span> <span class="number">-1</span>;  </span><br><span class="line">  <span class="keyword">else</span>      	</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器array"><a class="markdownIt-Anchor" href="#使用容器array"></a> 使用容器array</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174112655.png" alt="image-20211221174112655"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;array&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//qsort, bsearch, NULL</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> jj01</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_array</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;\ntest_array().......... \n&quot;</span>;    </span><br><span class="line">    </span><br><span class="line">array&lt;<span class="keyword">long</span>,ASIZE&gt; c;  				</span><br><span class="line"><span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();									</span><br><span class="line">    	<span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; ASIZE; ++i) &#123;</span><br><span class="line">        	c[i] = <span class="built_in">rand</span>(); </span><br><span class="line">    	&#125;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">        </span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;array.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;		</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;array.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	<span class="comment">//数组的第一个元素</span></span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;array.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;	<span class="comment">//数组的最后一个元素</span></span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;array.data()= &quot;</span> &lt;&lt; c.<span class="built_in">data</span>() &lt;&lt; endl;<span class="comment">//数组在内存中的起点地址</span></span><br><span class="line">	</span><br><span class="line"><span class="keyword">long</span> target = <span class="built_in">get_a_target_long</span>();</span><br><span class="line"></span><br><span class="line">		timeStart = <span class="built_in">clock</span>();</span><br><span class="line">    	::<span class="built_in">qsort</span>(c.<span class="built_in">data</span>(), ASIZE, <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="keyword">long</span>), compareLongs); <span class="comment">//快速排序</span></span><br><span class="line"><span class="keyword">long</span>* pItem = (<span class="keyword">long</span>*)::<span class="built_in">bsearch</span>(&amp;target, (c.<span class="built_in">data</span>()), ASIZE, <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="keyword">long</span>), compareLongs); <span class="comment">//二分查找</span></span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;qsort()+bsearch(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	<span class="comment">//快排和二分查找花费的时间    </span></span><br><span class="line">  		<span class="keyword">if</span> (pItem != <span class="literal">NULL</span>)</span><br><span class="line">    		cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">  		<span class="keyword">else</span></span><br><span class="line">    		cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器vector"><a class="markdownIt-Anchor" href="#使用容器vector"></a> 使用容器vector</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174129065.png" alt="image-20211221174129065"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174140679.png" alt="image-20211221174140679"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span> 	<span class="comment">//sort()</span></span></span><br><span class="line"><span class="keyword">namespace</span> jj02</span><br><span class="line">&#123;</span><br><span class="line">	<span class="function"><span class="keyword">void</span> <span class="title">test_vector</span><span class="params">(<span class="keyword">long</span>&amp; value)</span> </span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;\ntest_vector().......... \n&quot;</span>;</span><br><span class="line">	vector&lt;string&gt; c;  	</span><br><span class="line">	<span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line">	<span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    	<span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i) &#123;</span><br><span class="line">    		<span class="keyword">try</span> &#123;</span><br><span class="line">    			<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        		c.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf));     		</span><br><span class="line">			&#125; <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">				cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			     <span class="comment">//曾經最高 i=58389486 then std::bad_alloc</span></span><br><span class="line">				<span class="built_in">abort</span>(); <span class="comment">//退出程序</span></span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;vector.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	<span class="comment">//1073747823</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;vector.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;		<span class="comment">//元素个数</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;vector.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	<span class="comment">//第一个元素</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;vector.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;	<span class="comment">//最后一个元素</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;vector.data()= &quot;</span> &lt;&lt; c.<span class="built_in">data</span>() &lt;&lt; endl; <span class="comment">//vector的起始地址</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;vector.capacity()= &quot;</span> &lt;&lt; c.<span class="built_in">capacity</span>() &lt;&lt; endl &lt;&lt; endl;	<span class="comment">//容量，2倍增长	</span></span><br><span class="line">																				</span><br><span class="line">	string target = <span class="built_in">get_a_target_string</span>(); <span class="comment">//输入想查找的target</span></span><br><span class="line">    	&#123;</span><br><span class="line">			timeStart = <span class="built_in">clock</span>();</span><br><span class="line">	<span class="keyword">auto</span> pItem = ::<span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;  </span><br><span class="line">	 </span><br><span class="line">  			<span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">    			cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl &lt;&lt; endl;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl &lt;&lt; endl;</span><br><span class="line">    	&#125;</span><br><span class="line"></span><br><span class="line">		&#123;</span><br><span class="line">            timeStart = <span class="built_in">clock</span>();</span><br><span class="line">            <span class="built_in">sort</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>()); </span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;sort(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl; </span><br><span class="line">	</span><br><span class="line">			timeStart = <span class="built_in">clock</span>();	    </span><br><span class="line">		string* pItem = (string*)::<span class="built_in">bsearch</span>(&amp;target, (c.<span class="built_in">data</span>()), c.<span class="built_in">size</span>(), <span class="built_in"><span class="keyword">sizeof</span></span>(string), compareStrings); </span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;bsearch(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl; </span><br><span class="line">	   </span><br><span class="line">            <span class="keyword">if</span> (pItem != <span class="literal">NULL</span>)</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl &lt;&lt; endl;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl &lt;&lt; endl;	</span><br><span class="line">            &#125;</span><br><span class="line">	</span><br><span class="line">            c.<span class="built_in">clear</span>();</span><br><span class="line">            <span class="built_in">test_moveable</span>(vector&lt;MyString&gt;(),vector&lt;MyStrNoMove&gt;(), value);	</span><br><span class="line">		&#125;	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器list"><a class="markdownIt-Anchor" href="#使用容器list"></a> 使用容器list</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174159013.png" alt="image-20211221174159013"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;list&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span> <span class="comment">//find()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj03</span><br><span class="line">&#123;</span><br><span class="line">	<span class="function"><span class="keyword">void</span> <span class="title">test_list</span><span class="params">(<span class="keyword">long</span>&amp; value)</span> </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_list().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">    list&lt;string&gt; c;  	</span><br><span class="line">    <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();							</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                c.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf));    	</span><br><span class="line">            &#125; <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;list.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;list.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;    <span class="comment">//357913941</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;list.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;list.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;		</span><br><span class="line"></span><br><span class="line">    string target = <span class="built_in">get_a_target_string</span>();		</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">    <span class="keyword">auto</span> pItem = <span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);						</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line"></span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">        c.<span class="built_in">sort</span>();	<span class="comment">//非标准库的sort，而是容器中的sort					</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;c.sort(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		    	</span><br><span class="line"></span><br><span class="line">        c.<span class="built_in">clear</span>();</span><br><span class="line">        <span class="built_in">test_moveable</span>(list&lt;MyString&gt;(),list&lt;MyStrNoMove&gt;(), value);								</span><br><span class="line">    &#125;	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器forward_list"><a class="markdownIt-Anchor" href="#使用容器forward_list"></a> 使用容器forward_list</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174223453.png" alt="image-20211221174223453"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;forward_list&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj04</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test_forward_list</span><span class="params">(<span class="keyword">long</span>&amp; value)</span> </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_forward_list().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">    forward_list&lt;string&gt; c;  	</span><br><span class="line">    <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                c.<span class="built_in">push_front</span>(<span class="built_in">string</span>(buf));  			   		</span><br><span class="line">            &#125; <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;forward_list.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;  <span class="comment">//536870911</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;forward_list.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">		<span class="comment">//! cout &lt;&lt; &quot;forward_list.back()= &quot; &lt;&lt; c.back() &lt;&lt; endl; //no such member function</span></span><br><span class="line">        <span class="comment">//! cout &lt;&lt; &quot;forward_list.size()= &quot; &lt;&lt; c.size() &lt;&lt; endl; //no such member function</span></span><br><span class="line">            </span><br><span class="line">    string target = <span class="built_in">get_a_target_string</span>();	</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();			</span><br><span class="line">    	<span class="keyword">auto</span> pItem = <span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line"></span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">        c.<span class="built_in">sort</span>();						</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;c.sort(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line"></span><br><span class="line">        c.<span class="built_in">clear</span>();	 </span><br><span class="line">    &#125;											 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器slist"><a class="markdownIt-Anchor" href="#使用容器slist"></a> 使用容器slist</h3>
<p>slist是Gnu C 非标准库的单链表，slist——single list.</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174242385.png" alt="image-20211221174242385"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\slist&gt;</span></span></span><br><span class="line">	<span class="comment">//注意, 上一行並沒有引發警告訊息如 #include &lt;ext\hash_set&gt; 所引發者： </span></span><br><span class="line">	<span class="comment">//...\4.9.2\include\c++\backward\backward_warning.h	</span></span><br><span class="line">	<span class="comment">//[Warning] ...</span></span><br><span class="line">	</span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj10</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test_slist</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_slist().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">        __gnu_cxx::slist&lt;string&gt; c;  	</span><br><span class="line">        <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">        <span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                c.<span class="built_in">push_front</span>(<span class="built_in">string</span>(buf));     		</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;			</span><br><span class="line">    &#125;															</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器deque"><a class="markdownIt-Anchor" href="#使用容器deque"></a> 使用容器deque</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174258174.png" alt="image-20211221174258174"></p>
<p>deque是分段连续的，deque中每一个位置都指向一个buffer（图中所示），当空间不足的时候deque就新开辟一个buffer。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174312382.png" alt="image-20211221174312382"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;deque&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj05</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test_deque</span><span class="params">(<span class="keyword">long</span>&amp; value)</span> </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_deque().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">    deque&lt;string&gt; c;  	</span><br><span class="line">    <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                c.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;deque.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;deque.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;deque.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;deque.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	<span class="comment">//1073741821	</span></span><br><span class="line"></span><br><span class="line">   string target = <span class="built_in">get_a_target_string</span>();	</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();			</span><br><span class="line">   <span class="keyword">auto</span> pItem = <span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line"></span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">        ::<span class="built_in">sort</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>());	<span class="comment">//deque没有自己的sort算法，所以调用全局的sort					</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;::sort(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line"></span><br><span class="line">        c.<span class="built_in">clear</span>();</span><br><span class="line">        <span class="built_in">test_moveable</span>(deque&lt;MyString&gt;(),deque&lt;MyStrNoMove&gt;(), value);		 						</span><br><span class="line">    &#125;															</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器stack"><a class="markdownIt-Anchor" href="#使用容器stack"></a> 使用容器stack</h3>
<p>stack和queue本身没有组织结构，内部使用了deque，因为deque的功能更强大，包含了stack和queue的特性。</p>
<p>stack后进先出，没有迭代器指针，否则可能会修改栈中的数据，破坏了stack的特性。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174327487.png" alt="image-20211221174327487"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stack&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj17</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_stack</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_stack().......... \n&quot;</span>;</span><br><span class="line">     </span><br><span class="line">stack&lt;string&gt; c;  	</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line"><span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">push</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.top()= &quot;</span> &lt;&lt; c.<span class="built_in">top</span>() &lt;&lt; endl;	</span><br><span class="line">	c.<span class="built_in">pop</span>();</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.top()= &quot;</span> &lt;&lt; c.<span class="built_in">top</span>() &lt;&lt; endl;	</span><br><span class="line">	</span><br><span class="line">	</span><br><span class="line">	&#123;</span><br><span class="line">stack&lt;string, list&lt;string&gt;&gt; c;		<span class="comment">//以 list 為底層 </span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; <span class="number">10</span>; ++i) &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">push</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.top()= &quot;</span> &lt;&lt; c.<span class="built_in">top</span>() &lt;&lt; endl;	</span><br><span class="line">	c.<span class="built_in">pop</span>();</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.top()= &quot;</span> &lt;&lt; c.<span class="built_in">top</span>() &lt;&lt; endl;	</span><br><span class="line">    &#125;	</span><br><span class="line">	</span><br><span class="line">	&#123;</span><br><span class="line">stack&lt;string, vector&lt;string&gt;&gt; c;	<span class="comment">//以 vector 為底層 </span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; <span class="number">10</span>; ++i) &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">push</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.top()= &quot;</span> &lt;&lt; c.<span class="built_in">top</span>() &lt;&lt; endl;	</span><br><span class="line">	c.<span class="built_in">pop</span>();</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;stack.top()= &quot;</span> &lt;&lt; c.<span class="built_in">top</span>() &lt;&lt; endl;	</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">	&#123;</span><br><span class="line">stack&lt;string, set&lt;string&gt;&gt; c;	<span class="comment">//以 set 為底層 </span></span><br><span class="line"><span class="comment">/*!</span></span><br><span class="line"><span class="comment">    for(long i=0; i&lt; 10; ++i) &#123;</span></span><br><span class="line"><span class="comment">    		snprintf(buf, 10, &quot;%d&quot;, rand());</span></span><br><span class="line"><span class="comment">        	c.push(string(buf));    			 		</span></span><br><span class="line"><span class="comment">	&#125;</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;stack.size()= &quot; &lt;&lt; c.size() &lt;&lt; endl;</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;stack.top()= &quot; &lt;&lt; c.top() &lt;&lt; endl;	</span></span><br><span class="line"><span class="comment">	c.pop();</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;stack.size()= &quot; &lt;&lt; c.size() &lt;&lt; endl;</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;stack.top()= &quot; &lt;&lt; c.top() &lt;&lt; endl;	</span></span><br><span class="line"><span class="comment">	</span></span><br><span class="line"><span class="comment">//[Error] &#x27;class std::set&lt;std::basic_string&lt;char&gt; &gt;&#x27; has no member named &#x27;push_back&#x27;</span></span><br><span class="line"><span class="comment">//[Error] &#x27;class std::set&lt;std::basic_string&lt;char&gt; &gt;&#x27; has no member named &#x27;back&#x27;</span></span><br><span class="line"><span class="comment">//[Error] &#x27;class std::set&lt;std::basic_string&lt;char&gt; &gt;&#x27; has no member named &#x27;pop_back&#x27;</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">    &#125;</span><br><span class="line">			</span><br><span class="line"><span class="comment">//!stack&lt;string, map(string&gt;&gt; c5;	////以 map 為底層, [Error] template argument 2 is invalid</span></span><br><span class="line"><span class="comment">//!stack&lt;string&gt;::iterator ite1;  	//[Error] &#x27;iterator&#x27; is not a member of &#x27;std::stack&lt;std::basic_string&lt;char&gt; &gt;&#x27;</span></span><br><span class="line">		</span><br><span class="line">&#125;															</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器queue"><a class="markdownIt-Anchor" href="#使用容器queue"></a> 使用容器queue</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174342659.png" alt="image-20211221174342659"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;queue&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj18</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_queue</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_queue().......... \n&quot;</span>;</span><br><span class="line">     </span><br><span class="line">queue&lt;string&gt; c;  	</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line"><span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">push</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;		</span><br><span class="line">	c.<span class="built_in">pop</span>();</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;	</span><br><span class="line">	</span><br><span class="line">	</span><br><span class="line">	&#123;</span><br><span class="line">queue&lt;string, list&lt;string&gt;&gt; c;		<span class="comment">//以 list 為底層 </span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; <span class="number">10</span>; ++i) &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">push</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;		</span><br><span class="line">	c.<span class="built_in">pop</span>();</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;	</span><br><span class="line">    &#125;	</span><br><span class="line">	</span><br><span class="line">	&#123;</span><br><span class="line">queue&lt;string, vector&lt;string&gt;&gt; c;	<span class="comment">//以 vector 為底層 </span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; <span class="number">10</span>; ++i) &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">push</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;		</span><br><span class="line">	<span class="comment">//!c.pop();  //[Error] &#x27;class std::vector&lt;std::basic_string&lt;char&gt; &gt;&#x27; has no member named &#x27;pop_front&#x27;</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.front()= &quot;</span> &lt;&lt; c.<span class="built_in">front</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;queue.back()= &quot;</span> &lt;&lt; c.<span class="built_in">back</span>() &lt;&lt; endl;	</span><br><span class="line">    &#125;	</span><br><span class="line"></span><br><span class="line">	&#123;</span><br><span class="line">queue&lt;string, set&lt;string&gt;&gt; c;		<span class="comment">//以 set 為底層 </span></span><br><span class="line"><span class="comment">/*!</span></span><br><span class="line"><span class="comment">    for(long i=0; i&lt; 10; ++i) &#123;</span></span><br><span class="line"><span class="comment">    		snprintf(buf, 10, &quot;%d&quot;, rand());</span></span><br><span class="line"><span class="comment">        	c.push(string(buf));    			 		</span></span><br><span class="line"><span class="comment">	&#125;</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;queue.size()= &quot; &lt;&lt; c.size() &lt;&lt; endl;</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;queue.front()= &quot; &lt;&lt; c.front() &lt;&lt; endl;	</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;queue.back()= &quot; &lt;&lt; c.back() &lt;&lt; endl;		</span></span><br><span class="line"><span class="comment">	c.pop();</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;queue.size()= &quot; &lt;&lt; c.size() &lt;&lt; endl;</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;queue.front()= &quot; &lt;&lt; c.front() &lt;&lt; endl;	</span></span><br><span class="line"><span class="comment">	cout &lt;&lt; &quot;queue.back()= &quot; &lt;&lt; c.back() &lt;&lt; endl;</span></span><br><span class="line"><span class="comment">//[Error] &#x27;class std::set&lt;std::basic_string&lt;char&gt; &gt;&#x27; has no member named &#x27;push_back&#x27;</span></span><br><span class="line"><span class="comment">//[Error] &#x27;class std::set&lt;std::basic_string&lt;char&gt; &gt;&#x27; has no member named &#x27;front&#x27;</span></span><br><span class="line"><span class="comment">//[Error] &#x27;class std::set&lt;std::basic_string&lt;char&gt; &gt;&#x27; has no member named &#x27;pop_front&#x27;</span></span><br><span class="line"><span class="comment">*/</span>		</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">//! queue&lt;string, map&lt;string&gt;&gt; c5;	//以 map 為底層, [Error] template argument 2 is invalid</span></span><br><span class="line"><span class="comment">//! queue&lt;string&gt;::iterator ite1;  	//[Error] &#x27;iterator&#x27; is not a member of &#x27;std::queue&lt;std::basic_string&lt;char&gt; &gt;&#x27;	</span></span><br><span class="line">&#125;															</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器multiset"><a class="markdownIt-Anchor" href="#使用容器multiset"></a> 使用容器multiset</h3>
<p>底层是<em>红黑树</em>。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174357857.png" alt="image-20211221174357857"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj06</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test_multiset</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_multiset().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">        multiset&lt;string&gt; c;  	</span><br><span class="line">        <span class="keyword">char</span> buf[<span class="number">10</span>];		</span><br><span class="line">        <span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                c.<span class="built_in">insert</span>(<span class="built_in">string</span>(buf));  <span class="comment">//插入元素   				</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;multiset.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;multiset.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	<span class="comment">//214748364</span></span><br><span class="line"></span><br><span class="line">    	string target = <span class="built_in">get_a_target_string</span>();	</span><br><span class="line">        &#123;</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();</span><br><span class="line">    	<span class="keyword">auto</span> pItem = <span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);	<span class="comment">//比 c.find(...) 慢很多	使用的是标准库的通用的查找算法</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        &#123;</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">   		<span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);		<span class="comment">//比 std::find(...) 快很多	使用的是容器的查找算法						</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		 </span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line">        &#125;	</span><br><span class="line"></span><br><span class="line">        c.<span class="built_in">clear</span>();</span><br><span class="line">        <span class="built_in">test_moveable</span>(multiset&lt;MyString&gt;(),multiset&lt;MyStrNoMove&gt;(), value);	 						</span><br><span class="line">    &#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器multimap"><a class="markdownIt-Anchor" href="#使用容器multimap"></a> 使用容器multimap</h3>
<p>底层结构是<em>红黑树</em>，利用key找到value。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174538135.png" alt="image-20211221174538135"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj07</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test_multimap</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_multimap().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">        multimap&lt;<span class="keyword">long</span>, string&gt; c;  	</span><br><span class="line">        <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">    	<span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                <span class="comment">//multimap 不可使用 [] 做 insertion </span></span><br><span class="line">                c.<span class="built_in">insert</span>(pair&lt;<span class="keyword">long</span>,string&gt;(i,buf)); <span class="comment">//自己将key和value组合起来。此处的key都不相同，但是multimap中可以存放key相同的元素  						</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;multimap.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;multimap.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	<span class="comment">//178956970	</span></span><br><span class="line"></span><br><span class="line">    	<span class="keyword">long</span> target = <span class="built_in">get_a_target_long</span>();		</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">   	 	<span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);								</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	 </span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, value=&quot;</span> &lt;&lt; (*pItem).second &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	  </span><br><span class="line"></span><br><span class="line">        c.<span class="built_in">clear</span>();		  					</span><br><span class="line">    &#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器unordered_multiset"><a class="markdownIt-Anchor" href="#使用容器unordered_multiset"></a> 使用容器unordered_multiset</h3>
<p>底层使用<em>哈希表</em>。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174617363.png" alt="image-20211221174617363"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174628571.png" alt="image-20211221174628571"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj08</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test_unordered_multiset</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_unordered_multiset().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">        unordered_multiset&lt;string&gt; c;  	</span><br><span class="line">        <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">    	<span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                c.<span class="built_in">insert</span>(<span class="built_in">string</span>(buf));   			  		</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multiset.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multiset.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	<span class="comment">//357913941</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multiset.bucket_count()= &quot;</span> &lt;&lt; c.<span class="built_in">bucket_count</span>() &lt;&lt; endl;	<span class="comment">//哈希表可以存放的元素个数，每个bucket指向一条链表</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multiset.load_factor()= &quot;</span> &lt;&lt; c.<span class="built_in">load_factor</span>() &lt;&lt; endl;	<span class="comment">//装载因子</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multiset.max_load_factor()= &quot;</span> &lt;&lt; c.<span class="built_in">max_load_factor</span>() &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multiset.max_bucket_count()= &quot;</span> &lt;&lt; c.<span class="built_in">max_bucket_count</span>() &lt;&lt; endl;				</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">unsigned</span> i=<span class="number">0</span>; i&lt; <span class="number">20</span>; ++i) &#123;</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;bucket #&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; has &quot;</span> &lt;&lt; c.<span class="built_in">bucket_size</span>(i) &lt;&lt; <span class="string">&quot; elements.\n&quot;</span>;</span><br><span class="line">        &#125;					</span><br><span class="line"></span><br><span class="line">    	string target = <span class="built_in">get_a_target_string</span>();	</span><br><span class="line">        &#123;</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();</span><br><span class="line">    	<span class="keyword">auto</span> pItem = <span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);	<span class="comment">//比 c.find(...) 慢很多	</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        &#123;</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">    	<span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);		<span class="comment">//比 std::find(...) 快很多							</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	 </span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line">        &#125;		</span><br><span class="line"></span><br><span class="line">        c.<span class="built_in">clear</span>();</span><br><span class="line">        <span class="built_in">test_moveable</span>(unordered_multiset&lt;MyString&gt;(),unordered_multiset&lt;MyStrNoMove&gt;(), value);		 	 							</span><br><span class="line">    &#125;													 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器unordered_multimap"><a class="markdownIt-Anchor" href="#使用容器unordered_multimap"></a> 使用容器unordered_multimap</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174709030.png" alt="image-20211221174709030"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj09</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test_unordered_multimap</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;\ntest_unordered_multimap().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">        unordered_multimap&lt;<span class="keyword">long</span>, string&gt; c;  	</span><br><span class="line">        <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">    	<span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">                <span class="comment">//multimap 不可使用 [] 進行 insertion </span></span><br><span class="line">                c.<span class="built_in">insert</span>(pair&lt;<span class="keyword">long</span>,string&gt;(i,buf));</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">                <span class="built_in">abort</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multimap.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;	</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;unordered_multimap.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	<span class="comment">//357913941	</span></span><br><span class="line"></span><br><span class="line">    	<span class="keyword">long</span> target = <span class="built_in">get_a_target_long</span>();		</span><br><span class="line">        timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">    	<span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);								</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		 </span><br><span class="line">        <span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;found, value=&quot;</span> &lt;&lt; (*pItem).second &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;		</span><br><span class="line">    &#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>当需要进行大量的搜索的时候，最适合使用关联性容器。</p>
<h3 id="使用容器set"><a class="markdownIt-Anchor" href="#使用容器set"></a> 使用容器set</h3>
<p>放入的数据不能重复，key不能重复。底层使用<em>红黑树</em>。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174727606.png" alt="image-20211221174727606"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj13</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_set</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_set().......... \n&quot;</span>;</span><br><span class="line">     </span><br><span class="line">set&lt;string&gt; c;  	</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">insert</span>(<span class="built_in">string</span>(buf));     					</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;set.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;set.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	   <span class="comment">//214748364</span></span><br><span class="line">		</span><br><span class="line">string target = <span class="built_in">get_a_target_string</span>();	</span><br><span class="line">	&#123;</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();</span><br><span class="line"><span class="keyword">auto</span> pItem = <span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);	<span class="comment">//比 c.find(...) 慢很多	</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">	<span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">  	<span class="keyword">else</span></span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line"> 	&#125;</span><br><span class="line"> 	</span><br><span class="line"> 	&#123;</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();		</span><br><span class="line"><span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);		<span class="comment">//比 std::find(...) 快很多							</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		 </span><br><span class="line">	<span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">  	<span class="keyword">else</span></span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line"> 	&#125;							</span><br><span class="line">&#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器map"><a class="markdownIt-Anchor" href="#使用容器map"></a> 使用容器map</h3>
<p>放入的数据的key不能重复，底层使用的数据结构是<em>红黑树</em>。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174741620.png" alt="image-20211221174741620"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj14</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_map</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_map().......... \n&quot;</span>;</span><br><span class="line">     </span><br><span class="line">map&lt;<span class="keyword">long</span>, string&gt; c;  	</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line"><span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">			c[i] = <span class="built_in">string</span>(buf);  					</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;map.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;map.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;		<span class="comment">//178956970</span></span><br><span class="line">	</span><br><span class="line"><span class="keyword">long</span> target = <span class="built_in">get_a_target_long</span>();		</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();		</span><br><span class="line"><span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);								</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		 </span><br><span class="line">	<span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;found, value=&quot;</span> &lt;&lt; (*pItem).second &lt;&lt; endl;</span><br><span class="line">  	<span class="keyword">else</span></span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;			</span><br><span class="line">    	</span><br><span class="line">    c.<span class="built_in">clear</span>();					</span><br><span class="line">&#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器unordered_set"><a class="markdownIt-Anchor" href="#使用容器unordered_set"></a> 使用容器unordered_set</h3>
<p>底层是<em>哈希表</em>。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174804143.png" alt="image-20211221174804143"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174816521.png" alt="image-20211221174816521"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj15</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_unordered_set</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_unordered_set().......... \n&quot;</span>;</span><br><span class="line">     </span><br><span class="line">    unordered_set&lt;string&gt; c;  	</span><br><span class="line">    <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line">	<span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	c.<span class="built_in">insert</span>(<span class="built_in">string</span>(buf));    			 		</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_set.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_set.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;  <span class="comment">//357913941</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_set.bucket_count()= &quot;</span> &lt;&lt; c.<span class="built_in">bucket_count</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_set.load_factor()= &quot;</span> &lt;&lt; c.<span class="built_in">load_factor</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_set.max_load_factor()= &quot;</span> &lt;&lt; c.<span class="built_in">max_load_factor</span>() &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_set.max_bucket_count()= &quot;</span> &lt;&lt; c.<span class="built_in">max_bucket_count</span>() &lt;&lt; endl;			</span><br><span class="line">  	<span class="keyword">for</span> (<span class="keyword">unsigned</span> i=<span class="number">0</span>; i&lt; <span class="number">20</span>; ++i) &#123;</span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;bucket #&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; has &quot;</span> &lt;&lt; c.<span class="built_in">bucket_size</span>(i) &lt;&lt; <span class="string">&quot; elements.\n&quot;</span>;</span><br><span class="line">  	&#125;			</span><br><span class="line">	</span><br><span class="line">	string target = <span class="built_in">get_a_target_string</span>();	</span><br><span class="line">	&#123;</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();</span><br><span class="line">	<span class="keyword">auto</span> pItem = <span class="built_in">find</span>(c.<span class="built_in">begin</span>(), c.<span class="built_in">end</span>(), target);	<span class="comment">//比 c.find(...) 慢很多	</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;std::find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">	<span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">  	<span class="keyword">else</span></span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line"> 	&#125;</span><br><span class="line"> </span><br><span class="line"> 	&#123;</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();		</span><br><span class="line">	<span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);		<span class="comment">//比 std::find(...) 快很多							</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		 </span><br><span class="line">	<span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;found, &quot;</span> &lt;&lt; *pItem &lt;&lt; endl;</span><br><span class="line">  	<span class="keyword">else</span></span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;	</span><br><span class="line"> 	&#125;	</span><br><span class="line">&#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器unordered_map"><a class="markdownIt-Anchor" href="#使用容器unordered_map"></a> 使用容器unordered_map</h3>
<p>底层使用<em>哈希表</em>。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174844564.png" alt="image-20211221174844564"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj16</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_unordered_map</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_unordered_map().......... \n&quot;</span>;</span><br><span class="line"></span><br><span class="line">    unordered_map&lt;<span class="keyword">long</span>, string&gt; c;  	</span><br><span class="line">    <span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line">	<span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">			c[i] = <span class="built_in">string</span>(buf);  		</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_map.size()= &quot;</span> &lt;&lt; c.<span class="built_in">size</span>() &lt;&lt; endl;	<span class="comment">//357913941</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;unordered_map.max_size()= &quot;</span> &lt;&lt; c.<span class="built_in">max_size</span>() &lt;&lt; endl;	</span><br><span class="line">	</span><br><span class="line">	<span class="keyword">long</span> target = <span class="built_in">get_a_target_long</span>();		</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();	</span><br><span class="line">    <span class="comment">//! auto pItem = find(c.begin(), c.end(), target);	//map 不適用 std::find() 			</span></span><br><span class="line">    <span class="keyword">auto</span> pItem = c.<span class="built_in">find</span>(target);</span><br><span class="line">						</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;c.find(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		 </span><br><span class="line">	<span class="keyword">if</span> (pItem != c.<span class="built_in">end</span>())</span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;found, value=&quot;</span> &lt;&lt; (*pItem).second &lt;&lt; endl;</span><br><span class="line">  	<span class="keyword">else</span></span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;not found! &quot;</span> &lt;&lt; endl;		</span><br><span class="line">&#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器hash_multiset注意所在的头文件"><a class="markdownIt-Anchor" href="#使用容器hash_multiset注意所在的头文件"></a> 使用容器hash_multiset（注意所在的头文件）</h3>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">以下測試 hash_multiset, hash_multimap 過程中遇到阻礙：</span></span><br><span class="line"><span class="comment">headers &lt;hash_set&gt; 和 &lt;hash_map&gt; 各有兩個，</span></span><br><span class="line"><span class="comment">分別在 ...\4.9.2\include\c++\backward 和 ...\4.9.2\include\c++\ext，</span></span><br><span class="line"><span class="comment">不知要用哪一組! </span></span><br><span class="line"><span class="comment">用 &lt;ext\...&gt; 那一組會有問題 </span></span><br><span class="line"><span class="comment">   ...\4.9.2\include\c++\backward\hashtable.h </span></span><br><span class="line"><span class="comment">   [Error] no match for call to &#x27;(const hasher &#123;aka const __gnu_cxx::hash&lt;std::basic_string&lt;char&gt; &gt;&#125;) (const key_type&amp;)&#x27;</span></span><br><span class="line"><span class="comment">用 &lt;backward\...&gt; 那一組有相同的問題.  </span></span><br><span class="line"><span class="comment">so, 放棄測試 (no insertion or push_back or ...).  </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\hash_set&gt;</span>		</span></span><br><span class="line">    <span class="comment">//...\4.9.2\include\c++\backward\backward_warning.h	</span></span><br><span class="line">	<span class="comment">//[Warning] #warning This file includes at least one deprecated or antiquated header </span></span><br><span class="line">	<span class="comment">//which may be removed without further notice at a future date. </span></span><br><span class="line">	<span class="comment">//Please use a non-deprecated interface with equivalent functionality instead. </span></span><br><span class="line">	<span class="comment">//For a listing of replacement headers and interfaces, consult the file backward_warning.h. </span></span><br><span class="line">	<span class="comment">//To disable this warning use -Wno-deprecated. [-Wcpp]</span></span><br><span class="line">	</span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj11</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_hash_multiset</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_hash_multiset().......... \n&quot;</span>;</span><br><span class="line">   </span><br><span class="line">	__gnu_cxx::hash_multiset&lt;string&gt; c;  	</span><br><span class="line">	<span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line">    <span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	<span class="comment">//! c.insert(string(buf));     		</span></span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;				</span><br><span class="line">&#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用容器hash_multimap注意所在的头文件"><a class="markdownIt-Anchor" href="#使用容器hash_multimap注意所在的头文件"></a> 使用容器hash_multimap（注意所在的头文件）</h3>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\hash_map&gt;</span></span></span><br><span class="line">    <span class="comment">//...\4.9.2\include\c++\backward\backward_warning.h	</span></span><br><span class="line">	<span class="comment">//[Warning] #warning This file ... (如上個函數所言)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"><span class="keyword">namespace</span> jj12</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_hash_multimap</span><span class="params">(<span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_hash_multimap().......... \n&quot;</span>;</span><br><span class="line">     </span><br><span class="line">	__gnu_cxx::hash_multimap&lt;<span class="keyword">long</span>, string&gt; c;  	</span><br><span class="line">	<span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line">    <span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">        	<span class="comment">//c.insert(...   		</span></span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">	</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="comment">//! auto ite = c.find(...</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line">&#125;												</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>容器<code>hash_set</code>、<code>hash_map</code>、<code>hash_multiset</code>和<code>hash_multimap</code> 就是对应现在的<code>unordered</code>系列，但是这些容器还在，只不过所在的头文件可能发生了变化。</p>
<h2 id="分配器的测试"><a class="markdownIt-Anchor" href="#分配器的测试"></a> 分配器的测试</h2>
<p>理想情况下，容器有默认的分配器，使用者无需知道这个分配器。</p>
<h3 id="使用分配器allocator"><a class="markdownIt-Anchor" href="#使用分配器allocator"></a> 使用分配器allocator</h3>
<ul>
<li>GNU C 中容器的声明都是模板，模板一定有第二参数，且有默认值：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174910651.png" alt="image-20211221174910651"></p>
<ul>
<li>扩充的分配器不在标准库中，而是在<code>ext</code>文件夹下，且位于<code>__gnu_cxx</code>命名空间下：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174927488.png" alt="image-20211221174927488"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211221174942175.png" alt="image-20211221174942175"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;list&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> 		<span class="comment">//abort()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  		<span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span> 	<span class="comment">//find()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span> </span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstddef&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;memory&gt;</span>	<span class="comment">//內含 std::allocator  </span></span></span><br><span class="line">	<span class="comment">//欲使用 std::allocator 以外的 allocator, 得自行 #include &lt;ext\...&gt; </span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __GNUC__		</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\array_allocator.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\mt_allocator.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\debug_allocator.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\pool_allocator.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\bitmap_allocator.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\malloc_allocator.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ext\new_allocator.h&gt;</span>  </span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> jj20</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//pass A object to function template impl()，</span></span><br><span class="line"><span class="comment">//而 A 本身是個 class template, 帶有 type parameter T,  </span></span><br><span class="line"><span class="comment">//那麼有無可能在 impl() 中抓出 T, 創建一個 list&lt;T, A&lt;T&gt;&gt; object? </span></span><br><span class="line"><span class="comment">//以下先暫時迴避上述疑問.</span></span><br><span class="line">	</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_list_with_special_allocator</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __GNUC__	</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\ntest_list_with_special_allocator().......... \n&quot;</span>;</span><br><span class="line">     </span><br><span class="line">    <span class="comment">//不能在 switch case 中宣告，只好下面這樣. 				//1000000次 </span></span><br><span class="line">    list&lt;string, allocator&lt;string&gt;&gt; c1;						<span class="comment">//3140</span></span><br><span class="line">	list&lt;string, __gnu_cxx::malloc_allocator&lt;string&gt;&gt; c2;  	<span class="comment">//3110</span></span><br><span class="line">    list&lt;string, __gnu_cxx::new_allocator&lt;string&gt;&gt; c3; 		<span class="comment">//3156</span></span><br><span class="line">	list&lt;string, __gnu_cxx::__pool_alloc&lt;string&gt;&gt; c4;  		<span class="comment">//4922</span></span><br><span class="line">	list&lt;string, __gnu_cxx::__mt_alloc&lt;string&gt;&gt; c5; 		<span class="comment">//3297</span></span><br><span class="line">    list&lt;string, __gnu_cxx::bitmap_allocator&lt;string&gt;&gt; c6;  	<span class="comment">//4781 														</span></span><br><span class="line">	 </span><br><span class="line"><span class="keyword">int</span> choice;</span><br><span class="line"><span class="keyword">long</span> value;     </span><br><span class="line"></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;select: &quot;</span></span><br><span class="line">		 &lt;&lt; <span class="string">&quot; (1) std::allocator &quot;</span></span><br><span class="line">	     &lt;&lt; <span class="string">&quot; (2) malloc_allocator &quot;</span></span><br><span class="line">	     &lt;&lt; <span class="string">&quot; (3) new_allocator &quot;</span></span><br><span class="line">	     &lt;&lt; <span class="string">&quot; (4) __pool_alloc &quot;</span></span><br><span class="line">	     &lt;&lt; <span class="string">&quot; (5) __mt_alloc &quot;</span></span><br><span class="line">		 &lt;&lt; <span class="string">&quot; (6) bitmap_allocator &quot;</span>;</span><br><span class="line">	</span><br><span class="line">	cin &gt;&gt; choice;</span><br><span class="line">	<span class="keyword">if</span> ( choice != <span class="number">0</span> ) &#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;how many elements: &quot;</span>;</span><br><span class="line">		cin &gt;&gt; value; 		</span><br><span class="line">	&#125;</span><br><span class="line">			</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">10</span>];			</span><br><span class="line"><span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="keyword">try</span> &#123;</span><br><span class="line">    		<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, i);</span><br><span class="line">	        <span class="built_in"><span class="keyword">switch</span></span> (choice) </span><br><span class="line">	        &#123; <span class="comment">//每次push_back就会分配内存，每次分配内存就会使用到对应的分配器</span></span><br><span class="line">	 	        <span class="keyword">case</span> <span class="number">1</span> : 	c1.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf)); 	</span><br><span class="line">		 					<span class="keyword">break</span>;</span><br><span class="line">		        <span class="keyword">case</span> <span class="number">2</span> : 	c2.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf)); 	</span><br><span class="line">		 					<span class="keyword">break</span>;		</span><br><span class="line">		        <span class="keyword">case</span> <span class="number">3</span> : 	c3.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf)); </span><br><span class="line">		 					<span class="keyword">break</span>;		</span><br><span class="line">		        <span class="keyword">case</span> <span class="number">4</span> : 	c4.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf)); 	</span><br><span class="line">		 					<span class="keyword">break</span>;		</span><br><span class="line">		        <span class="keyword">case</span> <span class="number">5</span> : 	c5.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf)); 		</span><br><span class="line">		 					<span class="keyword">break</span>;		</span><br><span class="line">		        <span class="keyword">case</span> <span class="number">6</span> : 	c6.<span class="built_in">push_back</span>(<span class="built_in">string</span>(buf)); 	</span><br><span class="line">		 					<span class="keyword">break</span>;				</span><br><span class="line">		        <span class="keyword">default</span>: </span><br><span class="line">		 			<span class="keyword">break</span>;		</span><br><span class="line">	        &#125;    		   		</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="built_in"><span class="keyword">catch</span></span>(exception&amp; p) &#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;i=&quot;</span> &lt;&lt; i &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; p.<span class="built_in">what</span>() &lt;&lt; endl;	</span><br><span class="line">			<span class="built_in">abort</span>();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;a lot of push_back(), milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">	</span><br><span class="line">	 <span class="comment">//没有必要直接使用分配器，因为真正需要的是容器，但是如下还是直接进行了使用容器的测试</span></span><br><span class="line">	<span class="comment">//test all allocators&#x27; allocate() &amp; deallocate();</span></span><br><span class="line">	<span class="keyword">int</span>* p; 	</span><br><span class="line">    allocator&lt;<span class="keyword">int</span>&gt; alloc1;	</span><br><span class="line">	p = alloc1.<span class="built_in">allocate</span>(<span class="number">1</span>);  <span class="comment">//1表示分配一个int元素</span></span><br><span class="line">	alloc1.<span class="built_in">deallocate</span>(p,<span class="number">1</span>); <span class="comment">//归还的时候不仅需要指针，还要指定当初分配的元素个数，这样不好，所以不建议直接使用分配器。需要分配内存的时候，可以使用new/delete或malloc/free搭配	</span></span><br><span class="line">						</span><br><span class="line">	__gnu_cxx::malloc_allocator&lt;<span class="keyword">int</span>&gt; alloc2;  </span><br><span class="line">	p = alloc2.<span class="built_in">allocate</span>(<span class="number">1</span>);  </span><br><span class="line">	alloc2.<span class="built_in">deallocate</span>(p,<span class="number">1</span>);  	</span><br><span class="line">		</span><br><span class="line">    __gnu_cxx::new_allocator&lt;<span class="keyword">int</span>&gt; alloc3; 	</span><br><span class="line">	p = alloc3.<span class="built_in">allocate</span>(<span class="number">1</span>);  </span><br><span class="line">	alloc3.<span class="built_in">deallocate</span>(p,<span class="number">1</span>); 	</span><br><span class="line">		</span><br><span class="line">	__gnu_cxx::__pool_alloc&lt;<span class="keyword">int</span>&gt; alloc4;  	</span><br><span class="line">	p = alloc4.<span class="built_in">allocate</span>(<span class="number">2</span>);  </span><br><span class="line">	alloc4.<span class="built_in">deallocate</span>(p,<span class="number">2</span>); 	<span class="comment">//我刻意令參數為 2, 但這有何意義!! 一次要 2 個 ints? </span></span><br><span class="line">		</span><br><span class="line">	__gnu_cxx::__mt_alloc&lt;<span class="keyword">int</span>&gt; alloc5; 	</span><br><span class="line">	p = alloc5.<span class="built_in">allocate</span>(<span class="number">1</span>);  </span><br><span class="line">	alloc5.<span class="built_in">deallocate</span>(p,<span class="number">1</span>);  	</span><br><span class="line">			</span><br><span class="line">    __gnu_cxx::bitmap_allocator&lt;<span class="keyword">int</span>&gt; alloc6;  	</span><br><span class="line">	p = alloc6.<span class="built_in">allocate</span>(<span class="number">3</span>);  </span><br><span class="line">	alloc6.<span class="built_in">deallocate</span>(p,<span class="number">3</span>);  	<span class="comment">//我刻意令參數為 3, 但這有何意義!! 一次要 3 個 ints? </span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> 			</span></span><br><span class="line">&#125;															</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="第二讲"><a class="markdownIt-Anchor" href="#第二讲"></a> 第二讲</h1>
<h2 id="应具备的基础"><a class="markdownIt-Anchor" href="#应具备的基础"></a> 应具备的基础</h2>
<ul>
<li>
<p>C++基本语法</p>
</li>
<li>
<p>模板（Template）基础</p>
<p>令你事半功倍</p>
</li>
<li>
<p>数据结构（Data Structures）和算法（Algorithms）概念</p>
<p>令你如鱼得水</p>
</li>
</ul>
<p>书籍：</p>
<ul>
<li>《Algorithms + Data Structures = Programs》—— Niklaus Wirth，1976</li>
</ul>
<h2 id="源代码的分布vc-gcc"><a class="markdownIt-Anchor" href="#源代码的分布vc-gcc"></a> 源代码的分布（VC, GCC)</h2>
<p>所谓标准库，指规格是标准的，接口是标准的，但是不同的编译器可能有不同的实现。</p>
<h3 id="标准库版本visual-c"><a class="markdownIt-Anchor" href="#标准库版本visual-c"></a> 标准库版本，Visual C++</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170424184.png" alt="image-20211223170424184"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170541698.png" alt="image-20211223170541698"></p>
<h3 id="标准库版本gnu-c"><a class="markdownIt-Anchor" href="#标准库版本gnu-c"></a> 标准库版本，GNU C++</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170608518.png" alt="image-20211223170608518"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170629180.png" alt="image-20211223170629180"></p>
<p>Ubuntu下的C<ins>源码路径：/usr/include/c</ins></p>
<h2 id="oop面向对象编程-vs-gp泛型编程"><a class="markdownIt-Anchor" href="#oop面向对象编程-vs-gp泛型编程"></a> OOP(面向对象编程) vs. GP(泛型编程)</h2>
<ul>
<li>OOP：Object-Oriented programming</li>
<li>GP：Generic Programming</li>
</ul>
<p>C++标准库并不是用面向对象的概念设计出来的，面向对象的概念就是有封装、继承、多态（虚函数）。</p>
<p>标准库是利用泛型编程的概念设计出来的。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170724688.png" alt="image-20211223170724688"></p>
<ul>
<li>OOP将数据和操作关联到一起；</li>
<li><code>list</code>容器中有<code>sort</code>排序操作，为什么不像<code>vector</code>或者<code>deque</code>一样使用全局的排序函数呢？因为标准库的<code>sort</code>算法用到的迭代器需要一定的条件(RandomAccessIterator)，而这个条件是<code>list</code>提供的迭代器所不能满足的，所以链表不能像<code>vector</code>或<code>deque</code> 一样使用全局的 <code>sort</code> 算法。</li>
<li>如果容器中有<code>sort</code> 算法，则排序的时候使用容器中的排序算法；否则使用全局的排序算法。</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170743188.png" alt="image-20211223170743188"></p>
<ul>
<li><code>vector</code>和<code>deque</code> 容器中没有<code>sort</code>排序方法，只能使用全局的排序算法，这就是将数据和操作分开了，通过迭代器进行关联。</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170849235.png" alt="image-20211223170849235"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223170905933.png" alt="image-20211223170905933"></p>
<h2 id="技术基础操作符重载and模板泛化全特化偏特化"><a class="markdownIt-Anchor" href="#技术基础操作符重载and模板泛化全特化偏特化"></a> 技术基础：操作符重载and模板（泛化，全特化，偏特化）</h2>
<p><strong>阅读C++标准库源码的必要基础</strong></p>
<ul>
<li>Operator Overloading 操作符重载</li>
<li>Templates 模板</li>
</ul>
<h3 id="operator-overloading操作符重载"><a class="markdownIt-Anchor" href="#operator-overloading操作符重载"></a> Operator Overloading，操作符重载</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171159604.png" alt="image-20211223171159604"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171217055.png" alt="image-20211223171217055"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171327289.png" alt="image-20211223171327289"></p>
<h3 id="class-templates-类模板"><a class="markdownIt-Anchor" href="#class-templates-类模板"></a> Class Templates, 类模板</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171355498.png" alt="image-20211223171355498"></p>
<h3 id="function-templates函数模板"><a class="markdownIt-Anchor" href="#function-templates函数模板"></a> Function Templates，函数模板</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171421293.png" alt="image-20211223171421293"></p>
<h3 id="member-templates成员模板"><a class="markdownIt-Anchor" href="#member-templates成员模板"></a> Member Templates，成员模板</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171443931.png" alt="image-20211223171443931"></p>
<h3 id="specialization特化"><a class="markdownIt-Anchor" href="#specialization特化"></a> Specialization，特化</h3>
<p>例1：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171538209.png" alt="image-20211223171538209"></p>
<p>例2：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171552900.png" alt="image-20211223171552900"></p>
<p>例3：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171606981.png" alt="image-20211223171606981"></p>
<h3 id="partial-specialization偏特化"><a class="markdownIt-Anchor" href="#partial-specialization偏特化"></a> Partial Specialization，偏特化</h3>
<p>两个模板参数，绑定其中一个（个数的偏特化）；本来泛化可以接受任意类型，但是如果类型是指针，指向的类型还是由 T 决定，就进入<code>struct iterator_traits&lt;T*&gt;</code>（范围的偏特化）</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171636483.png" alt="image-20211223171636483"></p>
<h2 id="分配器allocators"><a class="markdownIt-Anchor" href="#分配器allocators"></a> 分配器allocators</h2>
<p>标准层面上，分配内存最终都会调用到<code>malloc</code>，然后各个操作系统调用不同的System API，得到内存。</p>
<h3 id="先谈operator-new-和-malloc"><a class="markdownIt-Anchor" href="#先谈operator-new-和-malloc"></a> 先谈operator new() 和 malloc()</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171746758.png" alt="image-20211223171746758"></p>
<p><code>malloc</code> 分配出来的比你需要的内存多，有很多附加的东西。需要的size越大，overhead（附加的内存）比例就较小；需要的size越小，附加的东西的比例就越大。</p>
<h3 id="vc6-stl对-allocator-的使用"><a class="markdownIt-Anchor" href="#vc6-stl对-allocator-的使用"></a> VC6 STL对 allocator 的使用</h3>
<ul>
<li>使用示例，如下容器使用的分配器是标准库中的<code>allocator</code>：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171816435.png" alt="image-20211223171816435"></p>
<ul>
<li>标准库中的<code>allocator</code>的实现：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171835762.png" alt="image-20211223171835762"></p>
<p>说明：</p>
<ol>
<li>分配内存的时候调用的是<code>allocator</code>的<code>allocate</code>函数，调用流程就变成了：<code>allocate</code> -&gt; <code>Allocate</code> -&gt; <code>operator new</code> -&gt; <code>malloc</code>；</li>
<li>回收内存的时候调用的是<code>allocator</code>的<code>deallocate</code>函数，调用流程：<code>deallocate</code> -&gt; <code>operator delete</code> -&gt; <code>free</code>；</li>
<li>直接使用分配器就是如图中所示的“分配512 ints”，<code>allocator&lt;int&gt;()</code>生成一个匿名对象，使用该对象进行函数的调用；</li>
<li>VC的分配器没有做任何独特的设计，只是调用了 C 的<code>malloc</code>和<code>free</code>来分配和释放内存，且接口设计并不方便程序员直接使用，但是容器使用就没问题。</li>
</ol>
<h3 id="bc5-stl对allocator的使用"><a class="markdownIt-Anchor" href="#bc5-stl对allocator的使用"></a> BC5 STL对allocator的使用</h3>
<ul>
<li>使用示例，BC5 STL中的一下容器使用的分配器是标准库的<code>allocator</code>：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171900497.png" alt="image-20211223171900497"></p>
<ul>
<li>BC5 中标准库的<code>allocator</code>的实现：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223171913193.png" alt="image-20211223171913193"></p>
<p>说明：和VC一样，<code>allocator</code>最终也是通过 C 的 <code>malloc</code> 和 <code>free</code>来分配和释放内存的。</p>
<h3 id="g29-stl对-allocator的使用"><a class="markdownIt-Anchor" href="#g29-stl对-allocator的使用"></a> G2.9 STL对 allocator的使用</h3>
<ul>
<li>G2.9 标准库中的分配器<code>allocator</code>的实现：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172016648.png" alt="image-20211223172016648"></p>
<p>说明：G2.9 标准库中的<code>allocator</code> 和 VC、BC一样，最终都是调用<code>malloc</code>和<code>free</code>进行内存的分配和释放。但是<mark>G2.9的STL中并没有使用标准库中的分配器，这个文件并没有被包含在任何STL头文件中，G2.9的STL容器使用的是<code>alloc</code>分配器</mark>。</p>
<ul>
<li>G2.9 STL容器使用的分配器是<code>alloc</code>：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172005073.png" alt="image-20211223172005073"></p>
<ul>
<li>G2.9 中的 <code>alloc</code> 的实现的行为模式：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172032944.png" alt="image-20211223172032944"></p>
<p>说明：</p>
<ol>
<li>这个<code>alloc</code>分配器的主要目的是减少<code>malloc</code>被调用的次数，因为<code>malloc</code>会带着额外开销；</li>
<li>设计了16条链表，每条链表负责不同大小区块的内存，#0负责8bytes大小的区块，#1负责16bytes大小的区块，以此类推…，超过这个分配器能管理的最大的区块128bytes，就仍然要调用<code>malloc</code>函数分配；</li>
<li>所有的容器，当它需要内存的时候都来向这个分配器要内存；容器中元素的大小会被调整为8的倍数；</li>
<li>更多内容，可查看<a target="_blank" rel="noopener" href="https://blog.csdn.net/u011386173/article/details/121872751?spm=1001.2014.3001.5501">C++内存管理机制</a>。</li>
</ol>
<h3 id="g49-stl对allocator的使用"><a class="markdownIt-Anchor" href="#g49-stl对allocator的使用"></a> G4.9 STL对allocator的使用</h3>
<ul>
<li>
<p>G4.9 标准库中的分配器<code>allocator</code>的实现：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172104403.png" alt="image-20211223172104403"></p>
</li>
</ul>
<p>说明：这个分配器也是直接调用的<code>malloc</code>和<code>free</code>进行内存的分配和回收，并没有其他的操作。</p>
<ul>
<li>G4.9 STL容器使用的分配器是<code>std::allocator</code>：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172052689.png" alt="image-20211223172052689"></p>
<p>说明：G4.9 的STL的容器使用的分配器是标准库的<code>allocator</code>分配器，而没有使用G2.9中的<code>alloc</code>分配器，为什么呢？那么G2.9中的分配器<code>alloc</code>在G4.9的版本中还在吗？</p>
<ul>
<li>G2.9中的<code>alloc</code>分配器在G4.9中还在，只是名称变了，名称现在是<code>__pool_alloc</code>：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172142223.png" alt="image-20211223172142223"></p>
<p>说明：</p>
<ol>
<li>之所以说<code>__pool_alloc</code>就是G2.9的<code>alloc</code>，因为相关的数值都仍然存在：管理8的倍数的区块，最大可以管理128字节的区块，有16条链表；</li>
<li>这种比较好的分配器仍然是可以使用的，使用方式如图中所示的“用例”，第二个模板参数指定分配器，<code>__pool_alloc</code>所在的命名空间为<code>__gun_cxx</code>；</li>
</ol>
<h2 id="容器之间的实现关系与分类"><a class="markdownIt-Anchor" href="#容器之间的实现关系与分类"></a> 容器之间的实现关系与分类</h2>
<h3 id="容器-结构与分类-2"><a class="markdownIt-Anchor" href="#容器-结构与分类-2"></a> 容器 — 结构与分类</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172246005.png" alt="image-20211223172246005"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172300440.png" alt="image-20211223172300440"></p>
<p>说明：</p>
<ol>
<li>
<p>如图中的注释说明，<strong>缩排</strong>表达的关系是复合，就是<code>set</code> 里面有<code>rb_tree</code>，<code>map</code>里面有<code>rb_tree</code>，<code>multiset</code>/<code>multimap</code>里面有<code>rb_tree</code>；</p>
</li>
<li>
<p>同理，<code>heap</code>中有<code>vector</code>，<code>priority_queue</code>中有<code>vector</code>，<code>priority_queue</code>中有<code>heap</code>；<code>stack</code>和<code>queue</code>中都有一个<code>deque</code>；</p>
</li>
<li>
<p>图中的左右两侧表示的是容器要操作数据必须有的指针或元素，这个整体的大小，不包括数据，通过<code>sizeof</code>计算：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172215059.png" alt="image-20211223172215059"></p>
</li>
</ol>
<h2 id="深度探索list"><a class="markdownIt-Anchor" href="#深度探索list"></a> 深度探索list</h2>
<h3 id="g29的list"><a class="markdownIt-Anchor" href="#g29的list"></a> G2.9的list</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172658562.png" alt="image-20211223172658562"></p>
<p>说明：</p>
<ol>
<li><code>list</code>中只有一个数据成员<code>node</code>，类型是<code>link_type</code>，而<code>link_type</code>就是<code>list_node*</code>，所以<code>node</code>就是一个指针，那么<code>sizeof(list) = 4</code>;</li>
<li><code>__list_node</code>中有两个指针<code>prev</code>和<code>next</code>，以及数据<code>data</code>，所以这就是一个双向链表，注意这里的<code>prev</code>和<code>next</code>指针是<code>void*</code>类型的，这种写法可以使用，但是必须进行强转型，这种方式不太好，在G4.9中已经进行了改善，这两个指针就指向<code>__list_node</code>类型；</li>
<li><code>list</code>中每个元素并不单纯的只有元素本身，还会多耗用两个指针<code>prev</code>和<code>next</code>，所以容器<code>list</code>向它的分配器要内存的时候，就是要“两个指针+数据”这么大的内存，而非只是数据这么多的内存；</li>
<li>链表是非连续的空间，所以它的<code>Iterator</code>不能是指针，因为<code>Iterator</code>模拟指针，就要能进行<ins>这些操作，但是如果<code>list</code>的<code>Iterator</code>进行<code>++</code> 操作不知道指到哪里去了；所以<code>Iteartor</code>必须足够聪明，当进行</ins>操作的时候知道要指向<code>list</code>的下一个节点；</li>
<li>除了<code>vector</code>和<code>array</code>外的所有容器的<code>iterator</code>都必须是class，它才能成为一个智能指针；</li>
<li>最后一个节点的下一个节点一定要加一个空白节点（图中的灰色节点），为了符合STL的「前闭后开」区间；<code>begin()</code>得到链表的第一个节点，<code>end()</code>得到链表的最后一个节点的下一个节点，即图中的空白节点；这是实现上的一个小技巧，不但是双向的，而且是环状的。</li>
</ol>
<h3 id="lists-iterator"><a class="markdownIt-Anchor" href="#lists-iterator"></a> list’s iterator</h3>
<ul>
<li>概览<code>list</code>的<code>iterator</code>：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172725770.png" alt="image-20211223172725770"></p>
<p>说明：</p>
<ol>
<li><code>iterator</code>要模拟指针，所以有大量的操作符重载；</li>
<li>所有的容器中的<code>iterator</code>都要做5个<code>typedef</code>，如上图中的所示的(1)(2)(3)(4)(5)；</li>
</ol>
<ul>
<li><code>iteartor</code>的<code>++</code>操作的实现：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172747899.png" alt="image-20211223172747899"></p>
<p>说明：</p>
<ol>
<li><code>i++</code>叫做postfix form，<code>++i</code>叫做prefix form，因为无论是前缀还是后缀形式，都只有<code>i</code> 这个参数，C++中为了区分这种情况，规定了<code>operator++()</code>无参表示前缀，此时的<code>i</code>已经变成调用这个函数的对象本身了；<code>operator++(int)</code>有参表示后缀；</li>
<li><code>self&amp; operator++()</code>函数可以成功的将<code>node</code>进行移动，指向下一个节点；</li>
<li>而<code>self operator++(int)</code>函数的流程是先记录原值，然后进行操作，最后返回原值。注意：
<ul>
<li>此时的记录原值的操作：<code>self tmp = *this；</code>并不会调用重载的<code>operator*</code>函数，因为这行代码先遇到了<code>=</code>运算符，所以会调用拷贝构造函数，此时的<code>*this</code>已经变成了拷贝构造函数里面的参数；</li>
<li><code>++*this</code> 调用了重载的<code>operator++()</code>函数；</li>
</ul>
</li>
<li>注意返回值的差别。之所以有差别是向整数的<code>++</code>操作看齐：整数里面是不允许进行两次后<code>++</code>的，所以这里<code>iterator</code>的<code>operator++(int)</code>为了阻止它做两次后<code>++</code>操作，返回值不是引用；整数中是允许做两次前<code>++</code>的操作，所以<code>iterator</code>的<code>opeartor++()</code>返回值是引用。</li>
</ol>
<ul>
<li><code>iterator</code>的<code>*</code>和<code>-&gt;</code>操作符的实现</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172817767.png" alt="image-20211223172817767"></p>
<p>说明：</p>
<ol>
<li><code>operator*</code> 就是获得<code>node</code>指针指向的节点的<code>data</code>数据；</li>
<li><code>operator-&gt;</code>获取<code>node</code>指针指向的节点的<code>data</code>数据的地址；</li>
</ol>
<ul>
<li>小结
<ol>
<li><code>list</code>是个双向链表，因为每个节点除了有<code>data</code>，还有<code>next</code>和<code>prev</code>指针；</li>
<li>所有的容器的<code>iterator</code>都有两大部分：（1）一些typedef；（2）操作符重载</li>
</ol>
</li>
<li>G4.9相比G2.9的改进：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172833959.png" alt="image-20211223172833959"></p>
<p>说明：</p>
<ol>
<li><code>iterator</code>的模板参数只有一个，容易理解；</li>
<li>G4.9中的指针<code>prev</code>和<code>next</code>是本身的类型，而不再是<code>void*</code>;</li>
</ol>
<h3 id="g49的list"><a class="markdownIt-Anchor" href="#g49的list"></a> G4.9的list</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223172940210.png" alt="image-20211223172940210"></p>
<p>说明：</p>
<ol>
<li>相比G2.9的<code>list</code>，G2.9的<code>list</code>更加复杂了；</li>
<li>因为行为模式已经在G2.9中知道了，所以没有必要再去看G4.9了；</li>
<li>和 G2.9一样，链表是环状双向的，刻意在环状<code>list</code>最后加了一个空白节点，用来符合STL的「前闭后开」区间；</li>
<li>在G2.9的<code>list</code>图中看到了，<code>sizeof(list)</code>在G2.9中是4，因为只有一个指针；而在G4.9中是8，为什么是8呢？
<ul>
<li>G4.9的<code>list</code>中本身没有数据，所以<code>size = 0</code>；但是它有父类<code>_List_base</code>，所以父类多大，它就多大；</li>
<li><code>_List_base</code>中的数据为<code>_M_impl</code>，所以这个数据多大，<code>_List_base</code>就多大；</li>
<li><code>_M_impl</code>类型为<code>_List_impl</code>，而<code>_List_impl</code>中的数据类型是<code>_List_node_base</code>;</li>
<li><code>_List_node_base</code>中有两个指针，所以<code>sizeof(list) = 8</code>。</li>
</ul>
</li>
</ol>
<h2 id="迭代器的设计原则和iterator-traits的作用与设计"><a class="markdownIt-Anchor" href="#迭代器的设计原则和iterator-traits的作用与设计"></a> 迭代器的设计原则和Iterator Traits的作用与设计</h2>
<p>设计Traits实现希望你放入的数据，能够萃取出你想要的特征。标准库中有好几种Traits，针对type的有type traits；针对characters，就有char traits；针对pointer，有pointer traits，… 。这里，只看iterator traits。</p>
<h3 id="iterator需要遵循的原则"><a class="markdownIt-Anchor" href="#iterator需要遵循的原则"></a> Iterator需要遵循的原则</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173005100.png" alt="image-20211223173005100"></p>
<p>说明：</p>
<ol>
<li><code>iterator</code>是算法和容器之间的桥梁，这样算法能知道要处理的元素的范围，容器将<code>begin()</code>和 <code>end()</code> 传出去交给算法，算法知道了范围且可以通过iterator进行移动，++或–，将元素一个一个地取出来；</li>
<li>算法在处理数据的过程中可能需要知道iterator的性质，因为它需要做动作，可能会选择最佳化的动作；</li>
<li>举例：有一个<code>rotate</code>算法，会想要知道iterator的哪些属性？
<ul>
<li>想要知道iterator的分类（<code>iteartor_traits&lt;_Iter&gt;::iterator_category()</code>)，有的迭代器只能++，或者只能–，有的可以跳着走，得到分类以便可以选取最佳的操作方式；</li>
<li>想要知道iterator的<code>difference_type</code>，两个iterator之间的距离；</li>
<li>想要知道iterator的<code>value_type</code>，指的是迭代器指向的元素的类型，比如在一个容器中放了10个string类型的元素，那么这个<code>value_type</code>就是<code>string</code>；</li>
</ul>
</li>
<li>算法提问，迭代器回答。这样的提问在C++标准库开发过程中设计出 5 种，这 5 种叫做iterator的associated types（相关类型）：
<ul>
<li><code>iterator_category</code></li>
<li><code>difference_type</code></li>
<li><code>value_type</code></li>
<li><code>reference</code></li>
<li><code>pointer</code></li>
</ul>
</li>
<li>iterator必须提供这5种相关类型，以便回答算法的提问。</li>
</ol>
<h3 id="iterator-必须提供的-5-种-associated-types"><a class="markdownIt-Anchor" href="#iterator-必须提供的-5-种-associated-types"></a> Iterator 必须提供的 5 种 associated types</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173043306.png" alt="image-20211223173043306"></p>
<p>说明：</p>
<ol>
<li>标准库中用<code>ptrdiff_t</code>来表示两个迭代器之间的距离，这个<code>ptrdiff_t</code>也是C++中定义的，但是如果实际存放的元素的头和尾的距离超过了这个<code>ptrdiff_t</code>类型表示的范围，那这就失效了；</li>
<li>因为<code>list</code>是个双向链表，所以这里使用了<code>bidirectional_iterator_tag</code>来表示<code>iterator_category</code>;</li>
<li>可以看到，这里并没有traits，那么为什么还要谈到iterator traits呢？因为如果 iterator 不是 class，就不能进行typedef，如果iterator是native pointer，即C++中的指针，它被视为一种退化的 iterator。所以当调用算法的时候，传入的可能是个指针，而不是泛化指针，不是个迭代器，那此时算法怎么提问呢？此时，才需要设计出 traits。</li>
</ol>
<h3 id="traits特性特征特质"><a class="markdownIt-Anchor" href="#traits特性特征特质"></a> Traits，特性，特征，特质</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173113966.png" alt="image-20211223173113966"></p>
<p>说明：</p>
<ol>
<li>图中的“萃取机”必须能区分它所收到的iterator，到底是以class设计的iterator还是native pointer的iterator；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173140798.png" alt="image-20211223173140798"></p>
<p>说明:</p>
<ol>
<li>因为算法不知道iterator是什么类型，所以不能直接提问，而是间接问。将iterator放入traits，算法问traits：value type是什么？</li>
<li>然后traits问iterator或指针：value type是什么？
<ul>
<li>若traits要问的对象是class iterator，则进入图中的①</li>
<li>若traits要问的对象是 pointer，则进入②或者③</li>
</ul>
</li>
<li>为了应付指针的形式，增加了中间层 iterator traits，利用了偏特化分离出指针和const指针；</li>
<li>这一页回答了算法的<code>value_type</code>的提问；</li>
</ol>
<h3 id="完整的iterator_traits"><a class="markdownIt-Anchor" href="#完整的iterator_traits"></a> 完整的iterator_traits</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173207147.png" alt="image-20211223173207147"></p>
<p>说明：如果是iterator，则进入泛化版本；如果是指针，则进入偏特化版本。算法问traits，当traits发现手上的东西是指针的时候，就由traits替它回答。</p>
<h3 id="各式各样的traits"><a class="markdownIt-Anchor" href="#各式各样的traits"></a> 各式各样的Traits</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173227595.png" alt="image-20211223173227595"></p>
<h2 id="深度探索vector"><a class="markdownIt-Anchor" href="#深度探索vector"></a> 深度探索vector</h2>
<p><code>vector</code>是一种动态增长的数组，当空间不够的时候，要到内存的其他地方开辟空间，并将原来的数据移动到新的空间，这才是扩充，不能在原来的空间进行扩充。</p>
<h3 id="g29的vector"><a class="markdownIt-Anchor" href="#g29的vector"></a> G2.9的vector</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173351711.png" alt="image-20211223173351711"></p>
<p>说明：</p>
<ol>
<li>当前<code>vector</code>的容量是8，目前已经存放了 6 个元素；</li>
<li>如果已经放了8个元素，要再放第9个元素的时候，就要进行扩充，如图中所示，二倍成长。容器回到内存中去找到另外的空间，要求是当前空间的2倍。当次数较多的时候，申请的空间就越来越大，如果最后找不到2倍大的空间，容器的生命就结束了，不能再放入元素了；</li>
<li>只需要三个指针<code>start</code>、<code>finish</code>、<code>end_of_storage</code>就能控制整个容器，因此，<code>sizeof(vector) = 12</code>;</li>
<li>所有的容器，如果带了连续的空间，就必须提供<code>[]</code>运算符重载函数；</li>
<li><code>vector</code>的 <mark>二倍成长</mark> 到底是怎么回事呢？</li>
</ol>
<ul>
<li><code>vector</code>的二倍成长的实现</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173412378.png" alt="image-20211223173412378"></p>
<p>说明：</p>
<ol>
<li><code>vector</code>的成长发生在放入元素的时候，此处即<code>push_back</code>函数；</li>
<li>之所以在<code>insert_aux</code>函数中也做了<code>finish == end_of_storage</code>的判断，是因为<code>insert_aux</code>除了被<code>push_back</code>函数调用外，还可能被其他函数调用，在那种情况下，就需要做检查；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173425324.png" alt="image-20211223173425324"></p>
<ol start="3">
<li>没有备用空间的时候，先记录下原来的<code>size</code>，分配原则：如果原大小为0，则分配1；如果原大小不为0，则分配原大小的2倍，前半段用来放置元数据，后半段准备用来放新数据；</li>
<li>确定了长度之后，使用分配器的<code>allocate</code>函数进行内存空间的分配；</li>
<li>然后将原来vector的内容拷贝到新的vector；</li>
<li>为新的元素设定初值；（要放入的第9个元素）；</li>
<li>因为<code>insert</code>操作也会使得空间发生增长，也会调用到这个<code>insert_aux</code>，所以要把安插点之后的内容也进行拷贝；</li>
<li>每次成长都会大量调用拷贝构造函数和析构函数（析构原来vector中的元素），需要很大的成本；</li>
</ol>
<h3 id="g29的vectors-iterator"><a class="markdownIt-Anchor" href="#g29的vectors-iterator"></a> G2.9的vector’s iterator</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173449114.png" alt="image-20211223173449114"></p>
<p>说明：</p>
<ol>
<li><code>vector</code>的空间是连续的，按理说可以直接使用指针作为迭代器，<code>vector</code>类中的<code>iterator</code>也的确是指针；</li>
<li>当算法要提问<code>iterator</code>的时候，就通过<code>iterator_traits</code>进行回答；当前的<code>iterator</code>是个指针，当它丢给萃取机萃取的时候，就是图中箭头指向的<code>T*</code>，因此萃取机就会进入偏特化的版本——<code>struct iterator_traits&lt;T*&gt;</code> ；</li>
</ol>
<h3 id="g49的vector"><a class="markdownIt-Anchor" href="#g49的vector"></a> G4.9的vector</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173524053.png" alt="image-20211223173524053"></p>
<p>说明：</p>
<ol>
<li>G4.9的<code>vector</code>也有三个指针，<code>_M_start</code>、<code>_M_finish</code>、<code>_M_end_of_storage</code>，所以 <code>sizeof(vector) = 12</code>；</li>
</ol>
<h3 id="g49的vectors-iterator"><a class="markdownIt-Anchor" href="#g49的vectors-iterator"></a> G4.9的vector’s iterator</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173605425.png" alt="image-20211223173605425"></p>
<p>说明：</p>
<ol>
<li>G4.9的<code>vector</code>的<code>iterator</code>经过层层推导就是<code>T*</code>外包裹一个iterator adapter，使得能支持 5 种 associated types;</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173620723.png" alt="image-20211223173620723"></p>
<ol start="2">
<li>算法向iterator提问的时候，将iterator放入萃取机中，因为此时的iterator是个object，所以走图中的灰色细箭头这一条路径；</li>
<li>而在iterator内部本身就定义了 5 种 associated types；</li>
<li>绕了这么大一圈，最后和G2.9的iterator达到的是一样的效果；</li>
</ol>
<h2 id="深度探索array"><a class="markdownIt-Anchor" href="#深度探索array"></a> 深度探索array</h2>
<h3 id="tr1的array"><a class="markdownIt-Anchor" href="#tr1的array"></a> TR1的array</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173650236.png" alt="image-20211223173650236"></p>
<p>说明：</p>
<ol>
<li><code>array</code>相比<code>vector</code>更加简单，因为在C和C++语言中本身就存在数组，为什么要将数组包装成一个容器来使用呢？因为变成容器之后，就要遵循容器的规律、规则，即需要提供iterator迭代器，而这个迭代器又要提供五种相关的类型以便于让算法可以询问一些必要的信息，算法才能决定采取哪种最优的动作，如果没有进行这样的包装，<code>array</code>就被摒弃在六大部件之外，就不能享受算法、仿函数等与其交互的关系。</li>
<li>上述的是TR1(Technique report 1) 版本，是C<ins>的过渡版本，介于C</ins>1.0和C++2.0之间；</li>
<li><code>array</code>不能扩充，所以必须指定大小，如<code>array&lt;int, 10&gt; myArray;</code></li>
<li>没有构造函数，也没有析构函数；</li>
<li>因为<code>array</code>是连续的空间，所以它的迭代器可以用指针来单纯的指针来表现，不用再设计单独的class；</li>
</ol>
<h3 id="g49的array"><a class="markdownIt-Anchor" href="#g49的array"></a> G4.9的array</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173701515.png" alt="image-20211223173701515"></p>
<p>说明：</p>
<ol>
<li>
<p>数组的写法</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> a[<span class="number">100</span>]; <span class="comment">//OK</span></span><br><span class="line"><span class="keyword">int</span>[<span class="number">100</span>] b; <span class="comment">//fail</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> T[<span class="number">100</span>];</span><br><span class="line">T c; <span class="comment">//OK</span></span><br></pre></td></tr></table></figure>
<p>即此处的<code>_M_elems</code>变量是个数组；</p>
</li>
</ol>
<h2 id="深度探索forward_list"><a class="markdownIt-Anchor" href="#深度探索forward_list"></a> 深度探索forward_list</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173727443.png" alt="image-20211223173727443"></p>
<p>说明：<code>forward_list</code>是个单向链表，相比双向链表更加简单，因此此处不再赘述。</p>
<h2 id="深度探索deque-queue和stack"><a class="markdownIt-Anchor" href="#深度探索deque-queue和stack"></a> 深度探索deque、queue和stack</h2>
<h3 id="容器deque"><a class="markdownIt-Anchor" href="#容器deque"></a> 容器deque</h3>
<h4 id="g29的deque"><a class="markdownIt-Anchor" href="#g29的deque"></a> G2.9的deque</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173749834.png" alt="image-20211223173749834"></p>
<p>说明：</p>
<ol>
<li><code>deque</code>是分段连续，<code>deque</code>是个<code>vector</code>，其中的每个元素都是一个指针，这些指针分别指向不同的<code>buffer</code>;</li>
<li>如果当前空闲的最后一个<code>buffer</code>使用完了，要继续<code>push_back</code>，那么新分配一个<code>buffer</code>，并将其<code>deque</code>当前图上的倒数第二个空白位置指向这个buffer即可，这就是<mark>往后扩充</mark>；</li>
<li>同理，如果第一个空闲的<code>buffer</code>用完了，要继续<code>push_front</code>，再分配一个buffer，用<code>deque</code>中的第一个空白位置指向新分配的buffer即可，这就是<mark>向前扩充</mark>；</li>
<li>图中的蓝色部分是迭代器，<code>deque</code>的迭代器是class，其中包含了<code>cur</code>、<code>first</code>、<code>last</code>和<code>node</code>四个部分：
<ul>
<li>其中的<code>node</code>指的就是图中<code>deque</code>中指向buffer的指针，我们在这里把它暂时称为控制中心。一个迭代器能知道控制中心在哪里，当迭代器要++或–的时候就能够跳到另一个分段，因为分段的控制全部在这里；</li>
<li><code>first</code>和<code>last</code>指的是<code>node</code>所指向的buffer的头和尾（前闭后开），标识出buffer的边界，如果走到了边界，就要跳到下一个buffer；</li>
<li><code>cur</code>就是当前迭代器指向的元素；</li>
</ul>
</li>
<li>几乎所有的容器都维护了两个迭代器<code>start</code>和<code>finish</code>，分别指向头和尾；几乎所有的容器都提供两个函数，<code>begin()</code> 和 <code>end()</code>，其中<code>begin()</code>传回<code>start</code>，<code>end()</code>传回<code>finish</code>；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173817837.png" alt="image-20211223173817837"></p>
<p>说明：</p>
<ol>
<li>图中是G2.9的deque；</li>
<li>数据部分的<code>map</code>的类型是<code>T**</code>，占 4 个字节；</li>
<li>代码中的<code>iterator</code>中的数据为下图的<code>deque's iterator</code>中所示的<code>cur</code>、<code>first</code>、<code>last</code>和<code>node</code>，都是指针，所以deque’s iterator的大小为 16 字节，</li>
<li>那么一个<code>deque</code>的大小为“两个迭代器 + map + map_size&quot; = 16 * 2 + 4 + 4 = 40 bytes；</li>
<li><code>deque</code>是个模板类，有三个模板参数，第一个参数表示元素类型，第二个参数是分配器的类型，第三个参数是指每个buffer容纳的元素个数，允许指定buffer容纳的元素个数，默认值为0，<code>deque_buf_size</code>函数会根据该模板参数决定buffer中能容纳的元素具体个数；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173842824.png" alt="image-20211223173842824"></p>
<h4 id="dequetinsert"><a class="markdownIt-Anchor" href="#dequetinsert"></a> deque&lt;T&gt;::insert()</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173919849.png" alt="image-20211223173919849"></p>
<p>说明：</p>
<ol>
<li>聪明在于插入数据的时候会判断要插入的位置是离前面比较近还是后面比较近，离哪边近，就推动哪边的元素，因为每次推动元素都要调用构造函数和析构函数，挺花费时间的；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173935419.png" alt="image-20211223173935419"></p>
<ol start="2">
<li><code>insert_aux</code>首先检查要插入的点往前和往后，哪边需要移动的元素<code>index</code>哪边更少；即找到离头还是尾的距离更近，将距离近的哪边的元素进行推动以便放入新值；</li>
<li>在安插点上设定新的值；</li>
</ol>
<h4 id="deque如何模拟连续空间"><a class="markdownIt-Anchor" href="#deque如何模拟连续空间"></a> deque如何模拟连续空间</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223173958490.png" alt="image-20211223173958490"></p>
<p>说明：</p>
<ol>
<li><code>font()</code>返回第一个元素，<code>back()</code>返回最后一个元素，这里是利用<code>finish</code>进行倒推；</li>
<li><code>size()</code> 就是元素的个数，注意这里的<code>finish - start</code>，其中迭代器一定是对<code>-</code>进行了操作符重载；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174013620.png" alt="image-20211223174013620"></p>
<ol start="3">
<li><code>operator*</code>就是取值，迭代器取值就是获取迭代器的<code>cur</code>指向的值；</li>
<li><code>operator-</code>统计首尾迭代器之间的元素个数；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174025553.png" alt="image-20211223174025553"></p>
<ol start="5">
<li><code>operator++(int)</code>调用<code>operator()</code>，<code>operator--(int)</code>调用<code>operator--()</code>，都是只移动一个位置</li>
<li><code>operator++()</code>就是移动当前元素，移动之后检查是否到达buffer的边界，如果到了下一个边界，就跳到下一个buffer的起点；<code>operator--()</code>同理</li>
</ol>
<p>![image-20211223174035925](…/…/…/Library/Application Support/typora-user-images/image-20211223174035925.png)</p>
<ol start="7">
<li><code>operator+=</code>就是移动多个位置，先判断是否会跨越buffer；如果跨越buffer，要先计算跨越几个，然后退回控制中心，跨越之后再决定有几个要走</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174046616.png" alt="image-20211223174046616"></p>
<ol start="8">
<li><code>operator-=</code>利用了<code>operator+=</code></li>
<li><code>operator[]</code>将迭代器移动到第n个位置，获得第n个元素</li>
</ol>
<p>小结：deque的迭代器通过操作符重载可以欺骗使用者自己是连续，这种欺骗是善意的，可以让使用者更好地使用deque。</p>
<h4 id="g49的deque"><a class="markdownIt-Anchor" href="#g49的deque"></a> G4.9的deque</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174128722.png" alt="image-20211223174128722"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174149104.png" alt="image-20211223174149104"></p>
<p>说明：</p>
<ol>
<li>G4.9版本相比G2.9版本，又是从一个单一的class变成了复杂的多个class；每个容器的新版本都会设计为如图的这种继承和组合的关系；</li>
<li>此时的 <code>sizeof(deque&lt;int&gt;) = 40</code>，和G2.9版本的大小一样，就是数据成员<code>_M_impl</code>的大小，即<code>_Deque_impl</code>类中的数据成员的大小；</li>
<li>G4.9的 deque 的模板参数只有两个，不允许指派buffer size；</li>
<li><code>_M_map</code>指向的是控制中心，它是用<code>vector</code>来存放指向不同buffer的指针的，当它的空间不够的时候，会二倍增长，将当前的<code>vector</code>拷贝到新的空间的中段，为了让左边和右边有空闲，使得可以向前和向后扩充；</li>
</ol>
<h3 id="容器queue"><a class="markdownIt-Anchor" href="#容器queue"></a> 容器queue</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174231839.png" alt="image-20211223174231839"></p>
<p>说明：</p>
<ol>
<li>可以看到，deque是双向进出，stack是先进后出，queue是先进先出，那么只需要在queue和stack中内含deque，然后封锁住其中某些动作；</li>
<li>如图中所示，<code>queue</code>类中的数据成员是<code>deque</code>类型，所有的操作都是转去调用<code>deque</code>的接口来完成；</li>
</ol>
<h3 id="容器stack"><a class="markdownIt-Anchor" href="#容器stack"></a> 容器stack</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174255541.png" alt="image-20211223174255541"></p>
<p>说明：</p>
<ol>
<li>和<code>queue</code>类似，<code>stack</code> 内含了一个 <code>deque</code>，所有的操作都是转调用deque的接口完成。</li>
</ol>
<h3 id="queue和stack关于其-iterator-和底层结构"><a class="markdownIt-Anchor" href="#queue和stack关于其-iterator-和底层结构"></a> queue和stack，关于其 iterator 和底层结构</h3>
<h4 id="1-stack或queue都不允许遍历也不提供iterator"><a class="markdownIt-Anchor" href="#1-stack或queue都不允许遍历也不提供iterator"></a> 1、stack或queue都不允许遍历，也不提供iterator</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174332980.png" alt="image-20211223174332980"></p>
<p>说明：</p>
<ol>
<li><code>stack</code> 和 <code>queue</code> 都可以选择 <code>list</code> 或 <code>deque</code> 作为底层结构，默认是 <code>deque</code>，如图中所示，选择 <code>list</code> 作为底层结构也是可以的，可以成功编译和执行；</li>
<li><code>stack</code>和<code>queue</code>都 <mark>不允许</mark> 遍历，也不提供 <code>iterator</code>，因为<code>stack</code>的行为是先进后出，<code>queue</code>的行为是先进先出，如果允许任意插入元素的话就会干扰了这个行为模式，而<code>stack</code>和<code>queue</code>的行为是被全世界公认的，所以不允许放元素，而放元素要靠迭代器，所以根本就不提供迭代器，要取东西的时候只能从头或者尾拿；</li>
</ol>
<h4 id="2-queue不可选择vector作为底层结构stack可选择vector作为底层结构"><a class="markdownIt-Anchor" href="#2-queue不可选择vector作为底层结构stack可选择vector作为底层结构"></a> 2、queue不可选择vector作为底层结构，stack可选择vector作为底层结构</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174346490.png" alt="image-20211223174346490"></p>
<p>说明：</p>
<ol>
<li><code>stack</code> 可以选择<code>vector</code>作为底层结构；</li>
<li><code>queue</code>不可以选择<code>vector</code>作为底层结构；部分接口不能转调用<code>vector</code>，如图中所示的<code>pop()</code>，不能成功转调用，因为<code>vector</code>中没有<code>pop_front</code>这个成员函数，部分失败了；</li>
<li>通过<code>queue</code>测试使用<code>vector</code>作为底层结构的启示：使用模板的时候，编译器不会预先做全面的检查，用到多少检查多少。</li>
</ol>
<h4 id="3-stack和queue都不可选择set或map作为底层结构"><a class="markdownIt-Anchor" href="#3-stack和queue都不可选择set或map作为底层结构"></a> 3、stack和queue都不可选择set或map作为底层结构</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174359305.png" alt="image-20211223174359305"></p>
<p>说明：</p>
<ol>
<li><code>stack</code>和<code>queue</code> 都不可以选择 <code>set</code>或<code>map</code>作为底层结构，因为转调用的时候，调用不到正确的函数的话，这个结构就剔除了，不能作为候选；</li>
<li>图中示范了<code>stack</code>选择<code>set</code>作为底层结构出现的的错误，第一行编译通过，是因为上面说过编译器预先不会做前面的检查；而<code>stack&lt;string, map&lt;string&gt;&gt; c;</code>和<code>queue&lt;string, map&lt;string&gt;&gt; c;</code> 编译无法通是因为<code>map</code>使用的时候是key和value都要设置，这里使用错误，所以编译无法通过。</li>
</ol>
<h2 id="深度探索rb_tree"><a class="markdownIt-Anchor" href="#深度探索rb_tree"></a> 深度探索RB_tree</h2>
<p>之前谈到的容器都是 Sequence Containers，从本章开始，要讲解关联式容器，它非常有用，因为它查找和插入都很快。关联式容器可以想象成一个小型的数据库，数据库就是希望用key找到value，而关联式容器就带着这样的性质。在标准库中，关联式容器底层使用两种结构作为技术支持——红黑树和哈希表。</p>
<h3 id="红黑树简介"><a class="markdownIt-Anchor" href="#红黑树简介"></a> 红黑树简介</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174526646.png" alt="image-20211223174526646"></p>
<p>说明：</p>
<ol>
<li>Red-Black tree（红黑树）是平衡二叉查找树（balanced binary search tree）中常被使用的一种。平衡二叉查找树的特征：排列规则有利于 <code>search</code> 和 <code>insert</code>，并保持适度平衡——无任何节点过深。</li>
<li><code>rb_tree</code> 提供 ”遍历“ 操作及 <code>iterators</code>。按正常规则（<code>++ite</code>) 遍历，便能获得排序状态（sorted）。【注：<code>begin()</code>记录的是最左的节点，<code>end()</code>记录最右的节点】</li>
<li>我们<strong>不应</strong>使用 rb_tree 的 iterators 改变元素值（因为元素有其严谨排列规则）。编程层面（programming level）<strong>并未阻绝此事</strong>。如此设计是正确的，因为 rb_tree 即将为 set 和 map 服务（作为其底部支持），而 map 允许 <u>元素的data</u> 被改变，只有<u>元素的key</u> 才是不可被改变的。</li>
<li>rb_tree 提供两种 insertion 操作： <code>insert_unique()</code> 和 <code>insert_equal()</code>。前者表示节点的key一定在整个 tree 中独一无二，否则安插失败；后者表示节点的 key 可重复。</li>
</ol>
<h3 id="g29-容器rb_tree"><a class="markdownIt-Anchor" href="#g29-容器rb_tree"></a> G2.9 容器rb_tree</h3>
<ul>
<li>标准库中红黑树的实现</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174546788.png" alt="image-20211223174546788"></p>
<p>说明：</p>
<ol>
<li><code>rb_tree</code>是一个模板类，模板参数：
<ul>
<li><code>Value</code>：key 和 data 合成 value，其中的data也可能是其他的数据合起来的；</li>
<li><code>KeyOfValue</code>：如何取出value中的key；</li>
<li><code>Compare</code>：比较函数/仿函数；</li>
<li><code>Alloc</code>：分配器，默认为<code>alloc</code>；</li>
</ul>
</li>
<li>数据部分：
<ul>
<li><code>node_count</code>：<code>rb_tree</code>中的节点数量；</li>
<li><code>header</code>：指向<code>rb_tree_node</code>的指针；</li>
<li><code>key_compare</code>：<code>key</code>的大小比较规则；<code>Compare</code>仿函数，没有数据成员，所以大小为0，任何的编译器，对于大小为0的class，创建出来的对象的size一定为1；</li>
</ul>
</li>
<li>所以数据部分一共的大小是 9，但是因为内存对齐，以4的倍数进行对齐，所以 9 要调整为 12；</li>
<li>图中的双向链表中的天蓝色节点，是一个虚空节点，为了做「前闭后开」区间，刻意放入的，不是真正的元素；红黑树中的<code>header</code>也是类似的，刻意放入的，使得代码实现更加简单；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174608781.png" alt="image-20211223174608781"></p>
<ol start="5">
<li>
<p>直接使用<code>rb_tree</code>示例：</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">rb_tree&lt;<span class="keyword">int</span>, </span><br><span class="line">		<span class="keyword">int</span>, </span><br><span class="line">		identity&lt;<span class="keyword">int</span>&gt;, <span class="comment">//仿函数，重载了operator()函数，告诉红黑树要如何取得key，GNU C 独有的，不是标准库的一部分</span></span><br><span class="line">		less&lt;<span class="keyword">int</span>&gt;, <span class="comment">//key比较大小的方式，less是标准库的一部分</span></span><br><span class="line">		alloc&gt; </span><br><span class="line">myTree;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h3 id="使用容器rb_tree"><a class="markdownIt-Anchor" href="#使用容器rb_tree"></a> 使用容器rb_tree</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174628938.png" alt="image-20211223174628938"></p>
<h3 id="g49-容器_rb_tree"><a class="markdownIt-Anchor" href="#g49-容器_rb_tree"></a> G4.9 容器_Rb_tree</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174759972.png" alt="image-20211223174759972"></p>
<p>说明：</p>
<ol>
<li>G4.9版本相比G2.9版本，类结构发生了变化；</li>
<li>OO思想里面，类中包含一个指针指向另一个类，主体本身不做任何事情，都是通过指针指向的另一个类做事情，这中手法叫做Handle-Body；</li>
<li><code>set</code>和<code>map</code>里都各有一个<code>_Rb_tree</code>；</li>
<li>此时的<code>_Rb_tree</code>的数据的大小取决于<code>_M_impl</code>这个数据成员的大小，而<code>_M_impl</code>类型是<code>_Rb_tree_impl</code>；<code>Rb_tree_impl</code>中的数据成员<code>_M_node</code>的类型是<code>_Rb_tree_node_base</code>，其中包含了四个数据成员：3 个指针，1个<code>_Rb_tree_color</code>（enum枚举类型） = 24 bytes；</li>
</ol>
<h3 id="使用容器_rb_tree"><a class="markdownIt-Anchor" href="#使用容器_rb_tree"></a> 使用容器_Rb_tree</h3>
<p>G4.9版本相比于G2.9部分名称发生了改变，如下红色的部分就是改变的部分：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174714367.png" alt="image-20211223174714367"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174728444.png" alt="image-20211223174728444"></p>
<h2 id="深度探索setmultiset"><a class="markdownIt-Anchor" href="#深度探索setmultiset"></a> 深度探索set，multiset</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174824878.png" alt="image-20211223174824878"></p>
<ol>
<li>
<p><code>set/multiset</code> 以 <code>rb_tree</code>为底层结构，因此有「元素自动排序」特性。排序的依据是 key，而<strong>set/multiset 元素的 value 和 key 合一：value 就是 key</strong>。</p>
</li>
<li>
<p><code>set/multiset</code> 提供 ”遍历“操作及 iterators。按正常规则(++ite) 遍历，便能获得排序状态（sorted）。</p>
</li>
<li>
<p>我们<mark>无法</mark> 使用 <code>set/multiset</code> 的 iterators 改变元素值（因为key 有其严谨排列规则）。<code>set/multiset</code> 的 iterator 是其底部的 RB tree 的 const_iterator, 就是为了<mark>禁止</mark> user 对元素赋值。【注：讲解 rb_tree 的时候说到的是”不应“，因为Value 中的 data是可以更改的，是合理的；但是这里是”无法“，可见set在设计上就限制了不能修改，之所以不能修改，是因为set的key就是value，如果修改的话，改的就是key，这是不可以的。】</p>
</li>
<li>
<p><code>set</code> 元素的 key 必须独一无二，因此其 <code>insert()</code> 用的是 rb_tree 的 <code>insert_unique()</code>。</p>
</li>
<li>
<p><code>multiset</code> 元素的 key 可以重复，因此其<code>insert()</code> 用的是 rb_tree 的 <code>insert_equal()</code>。</p>
</li>
</ol>
<h4 id="容器set"><a class="markdownIt-Anchor" href="#容器set"></a> 容器set</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174840212.png" alt="image-20211223174840212"></p>
<p>说明：</p>
<ol>
<li><code>set</code>的模板参数有三个：Key的类型；Key的大小比较规则，默认值为<code>less&lt;Key&gt;</code>；分配器，默认值为<code>alloc</code>；</li>
<li><code>set</code>中有个红黑树变量<code>t</code>；</li>
<li>从<code>set</code>中拿 iterator 的时候拿的是 <code>rb_tree</code> 的 <code>const_iterator</code>，这个迭代器是不允许对元素进行修改的；</li>
<li><code>set</code>的所有操作，都转调用底层 <code>t</code>  的操作。从这层意义来看，<code>set</code> 未尝不是个 container adapter；</li>
<li>之前说到 key 和 data 合起来这一整包是 value，从 value 中取出 key 用<code>identity</code>，<code>set</code> 里面取出 key 也就需要用 <code>identity</code>；<code>identity</code> 是GNU C中才有的；</li>
</ol>
<h4 id="vc6-容器set"><a class="markdownIt-Anchor" href="#vc6-容器set"></a> VC6 容器set</h4>
<ul>
<li>VC6 不提供 <code>identity()</code>，那么其 <code>set</code> 和 <code>map</code> 如何使用 RB-tree？</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174903260.png" alt="image-20211223174903260"></p>
<p>说明：</p>
<ol>
<li>VC6中自己实现了一个内部类<code>_Kfn</code>，写法和 GNU C 中的<code>identity</code> 的实现是一样的，即自己实现。</li>
</ol>
<h4 id="使用容器multiset-2"><a class="markdownIt-Anchor" href="#使用容器multiset-2"></a> 使用容器multiset</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223174935649.png" alt="image-20211223174935649"></p>
<h2 id="深度探索mapmultimap"><a class="markdownIt-Anchor" href="#深度探索mapmultimap"></a> 深度探索map，multimap</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175007999.png" alt="image-20211223175007999"></p>
<p>说明：</p>
<ol>
<li>每个元素即value包含了key 和 data，key不能修改，但是 data 可以修改；</li>
</ol>
<h4 id="g29-的容器map"><a class="markdownIt-Anchor" href="#g29-的容器map"></a> G2.9 的容器map</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175024027.png" alt="image-20211223175024027"></p>
<p>说明：</p>
<ol>
<li><code>select1st</code>：从value中取出第一个，即取出key；<code>map</code>拿出key的方式就是<code>select1st</code>;</li>
<li><code>map</code>的迭代器就是红黑树的迭代器，红黑树的迭代器并没有禁止任何事情呀？那是如何做到用它不能修改key，但是能修改data的呢？如上例所示，使用者<code>map&lt;int,string&gt;</code>放入两个类型，被<code>map</code>包成一个 <code>pair</code>，而这个<code>pair</code>被当成红黑树的第二个模板参数，<code>map</code>自动地将<code>key</code>设置成 <code>const</code>，所以 key 放入之后无论如何都不能被修改，因为它是 const。<code>set</code> 中不能修改 key 是因为使用的迭代器是红黑树的 const_iterator，而<code>map</code>不允许通过迭代器修改key，是因为包装成 <code>pair</code>的时候将key设置成了 const；</li>
<li><code>select1st</code>是GNU C独有的；</li>
</ol>
<h4 id="vc6-的容器map"><a class="markdownIt-Anchor" href="#vc6-的容器map"></a> VC6 的容器map</h4>
<ul>
<li>VC6 不提供 <code>select1st()</code>，那么 <code>map</code> 如何使用 RB-tree？</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175043995.png" alt="image-20211223175043995"></p>
<p>说明：</p>
<ol>
<li>自己实现一个和<code>select1st</code>功能一样的类<code>_Kfn</code>，重载<code>operator()</code> 函数，所以是个函数对象/仿函数，将<code>pair</code> 的 <code>first</code> 数据传回；</li>
</ol>
<h4 id="使用容器multimap-2"><a class="markdownIt-Anchor" href="#使用容器multimap-2"></a> 使用容器multimap</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175103875.png" alt="image-20211223175103875"></p>
<h4 id="容器map独特的operator"><a class="markdownIt-Anchor" href="#容器map独特的operator"></a> 容器map，独特的operator[]</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175129044.png" alt="image-20211223175129044"></p>
<p>说明：</p>
<ol>
<li><code>map</code>的 <code>[]</code>操作：如果key存在，则返回 key 对应的 data；如果key不存在，那么会创建一个pair，使用默认值作为data，当前的key为key；</li>
<li>使用<code>lower_bound</code>查找元素value，如果找到了，则返回一个iterator指向其中第一个元素；如果没有，就返回该元素应该插入的位置，即返回iterator指向第一个「不小于value」的元素。</li>
</ol>
<h4 id="使用容器map-2"><a class="markdownIt-Anchor" href="#使用容器map-2"></a> 使用容器map</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175148989.png" alt="image-20211223175148989"></p>
<h2 id="深度探索hashtable"><a class="markdownIt-Anchor" href="#深度探索hashtable"></a> 深度探索hashtable</h2>
<ul>
<li>引子</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175206845.png" alt="image-20211223175206845"></p>
<p>说明：假设有N个object，每个有一个对应的编号，当空间足够的时候，就将object放到对应编号的位置上；当空间不足的时候，object的编号 % 表的长度，此时就可能出现多个object应落在同一个位置，出现了<mark>碰撞💥</mark>；</p>
<ul>
<li>Separate Chaining 解决碰撞</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175221195.png" alt="image-20211223175221195"></p>
<p>说明：</p>
<ol>
<li>如果发生碰撞，就使用链表串起来，这种方法叫做 Separate Chaining；</li>
<li>如图上所示，55、2、108这三个数，模53，结果都是2，所以都落在#2 bucket所指向的这条链表上；</li>
<li>如果链表很长，那么搜索速度就很慢，所以就需要一个方法来判断链表是否很长，如果很长就需要打散重新放置；</li>
<li>判断链表很长的方法，不涉及到数学，纯由经验所得：如果元素个数比bucket个数多，就需要打散。</li>
<li>打散方法：bucket增加到比原来size2倍大的附近的质数，重新计算元素应该落在哪个bucket中。这是GNU C中的实现。</li>
<li>例：如上图中所示，一开始放置了 6 个元素，分别落在图中的不同的bucket中，再放入 48个元素，则总量达到54，大于bucket size，所以重新进行哈希，而此时将bucket size增加到 97，因为97是53的2倍大的附近的质数，然后将元素分别模97，得到结果是多少，就落在哪个bucket中；</li>
</ol>
<ul>
<li>GNU C中hashtable的实现</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175310483.png" alt="image-20211223175310483"></p>
<p>说明：</p>
<ol>
<li>模板参数：
<ul>
<li><code>HashFcn</code> : 每个元素通过什么方法得到编号，是个函数或者仿函数，计算出来的编号叫做hashCode；</li>
<li><code>ExtracKey</code>：提取出key；</li>
<li><code>EqualKey</code>：Key比较大小的方式；</li>
</ul>
</li>
<li>数据成员：
<ul>
<li>三个函数对象：<code>hash</code>、<code>equals</code>、<code>get_key</code> ，理论值大小都为0，但是因为实际的某些因素，只能为1，所以一共是3bytes；</li>
<li>vector类型的<code>buckets</code>，<code>vector</code>中有3个指针，所以本身是12 bytes；</li>
<li><code>num_elements</code>：元素个数，4bytes</li>
<li>所以一共：4 + 12 + 3 = 19bytes，内存对齐，调整为4的倍数，所以为20bytes；</li>
</ul>
</li>
<li>GNU C中的串联元素的链表是单向链表；</li>
<li>图中有个小错误： <code>cur</code> 应该指向某个元素，而不是指向bucket；</li>
<li>迭代器必须有能力在走到链表的尽头的时候回到buckets中，找到下一个bucket；</li>
</ol>
<ul>
<li>直接使用容器hashtable</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175326136.png" alt="image-20211223175326136"></p>
<p>说明：</p>
<ol>
<li><code>eqstr</code>规定字符串比较内容，而不是比较指针;</li>
<li>决定元素的编号的方法是hash-function；本例子中使用的是<code>hash&lt;const char*&gt;</code>，处理C风格的字符串，转成编号，这个就是指定如下的特化版本中的<code>__STL_TEMPLATE_NULL struct hash&lt;const char*&gt;</code> 这个特化版本。</li>
</ol>
<ul>
<li>hash-function, hash-code</li>
</ul>
<p><code>hash-function</code>传出来的东西就叫做<code>hash-code</code>。</p>
<p><code>hash</code>方法的泛化和特化版本：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175355949.png" alt="image-20211223175355949"></p>
<p>说明：</p>
<ol>
<li>上图接收的都是数值的情况，hash-function就将数值当做编号；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175423626.png" alt="image-20211223175423626"></p>
<ol start="2">
<li>
<p>上图接收的是字符串的情况，调用<code>__stl_hash_string</code>函数生成对应的编号，C++标准库中针对字符串的情况已经设计好了hash-function；</p>
</li>
<li>
<p>如果放入的元素不是已经特化的版本，就要自己实现，标准库G2.9中没有提供现成的<code>hash&lt;std::string&gt;</code>；</p>
</li>
</ol>
<ul>
<li>modulus运算</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175442749.png" alt="image-20211223175442749"></p>
<p>说明：</p>
<ol>
<li>modulus运算就是模运算，计算得到余数。</li>
<li>左边的是hashtable中的函数，计算元素要落在哪个bucket中，最后都是通过<code>hash(key) % n</code> 决定；</li>
</ol>
<ul>
<li>hash-code的计算示例</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175456957.png" alt="image-20211223175456957"></p>
<h4 id="g29-hashtable的使用"><a class="markdownIt-Anchor" href="#g29-hashtable的使用"></a> G2.9 hashtable的使用</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175516300.png" alt="image-20211223175516300"></p>
<h4 id="g49-hashtable的使用"><a class="markdownIt-Anchor" href="#g49-hashtable的使用"></a> G4.9 hashtable的使用</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175543473.png" alt="image-20211223175543473"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175621996.png" alt="image-20211223175621996"></p>
<h2 id="unorder容器概念"><a class="markdownIt-Anchor" href="#unorder容器概念"></a> unorder容器概念</h2>
<ul>
<li>到了C++11，以<code>hash_xx</code>开头的容器都更名为<code>unordered_xx</code></li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175640216.png" alt="image-20211223175640216"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175650302.png" alt="image-20211223175650302"></p>
<ul>
<li>使用容器unordered_set</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175711678.png" alt="image-20211223175711678"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211223175735873.png" alt="image-20211223175735873"></p>
<p>说明：</p>
<ol>
<li>
<p>buckets size一定大于元素数量；</p>
</li>
<li>
<p>图中因为<code>unordered_set</code>不能放入重复的数据，随机数的范围是0 ~ 32767，所以<code>unordered_set.size()= 32768</code>，而<code>unordered_set.bucket_count() = 62233</code>，即buckets size 比 元素个数大；</p>
</li>
<li>
<p>如果使用的是<code>unordered_multiset</code>，放入100万个元素，那么buckets size 一定是大于 100万的；</p>
</li>
</ol>
<h1 id="第三讲"><a class="markdownIt-Anchor" href="#第三讲"></a> 第三讲</h1>
<h2 id="算法的形式"><a class="markdownIt-Anchor" href="#算法的形式"></a> 算法的形式</h2>
<ul>
<li>C++标准库的算法，是什么东西？</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181041775.png" alt="image-20211228181041775"></p>
<p>说明：</p>
<ol>
<li>
<p>算法Algorithm 是个 function template，标准库中的算法都长成如下这样：</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> Iterator&gt;</span></span><br><span class="line"><span class="function"><span class="title">Algorithm</span><span class="params">(Iterator itr1, Iterator itr2)</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> Iterator, <span class="keyword">typename</span> Cmp&gt;</span></span><br><span class="line"><span class="function"><span class="title">Algorithm</span><span class="params">(Iterator itr1, Iterator itr2, Cmp comp)</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>算法看不见容器，对其一无所知；所以，它所需要的一切信息都必须从Iterators取得，而Iterators（由Containers供应）必须能够回答Algorithm的所有提问，才能搭配该 Algorithm 的所有操作；</p>
</li>
<li>
<p>如果算法提问，迭代器无法回答，那么编译到那一行就会报错；</p>
</li>
</ol>
<h2 id="迭代器的分类"><a class="markdownIt-Anchor" href="#迭代器的分类"></a> 迭代器的分类</h2>
<h3 id="各种容器的iterators的iterator_category"><a class="markdownIt-Anchor" href="#各种容器的iterators的iterator_category"></a> 各种容器的<code>iterators</code>的<code>iterator_category</code></h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181107336.png" alt="image-20211228181107336"></p>
<p>说明：</p>
<ol>
<li>迭代器是由容器提供的
<ul>
<li><code>Array</code>和<code>Vector</code>都是<mark>连续空间</mark>，所以它们的迭代器应该是<code>Random_Access</code>；</li>
<li><code>Deque</code>是<mark>分段连续</mark>的，是假的连续，但是给使用者的感觉是真的连续，所以它的迭代器也应该是<code>Random_Access</code>；</li>
<li><code>list</code>是双向链表，空间不是连续的，所以它的迭代器是<code>bidirection</code>, 可以往前，也可以往后，但是不能跳跃；</li>
<li><code>forward_list</code>是单向链表，所以它的迭代器是<code>forward_iterator</code>；</li>
<li><code>set</code>/<code>map</code>/<code>multiset</code>/<code>multimap</code>底层结构都是红黑树，红黑节点之间是双向的，所以它们的迭代器都是<code>bidirection</code>这种类型；</li>
<li><code>unordered</code>系列的容器底层是<code>Hashtable</code>，每个bucket下是一个链表，所以要看这个链表是单向还是双向的，才能决定hashtable是<code>forward</code> 还是 <code>bidirection</code>类型；</li>
</ul>
</li>
<li>容器提供的迭代器的分类不是1，2，3，4，5这样的整数，而是如上所示的这种对象。五种iterator category，都是类，且存在继承关系：
<ul>
<li><code>input_iterator_tag</code></li>
<li><code>forward_iterator_tag</code></li>
<li><code>bidirectional_iterator_tag</code></li>
<li><code>random_access_iterator_tag</code></li>
<li><code>output_iterator_tag</code></li>
</ul>
</li>
<li>如下程序打印出各种容器的迭代器的分类的形式：</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181141617.png" alt="image-20211228181141617"></p>
<p>程序说明：</p>
<ol>
<li>传入各种容器的迭代器给<code>dispaly_category(I itr)</code>函数，其中类似<code>array&lt;int,10&gt;::iterator()</code>的形式是个临时对象，没有名称；</li>
<li><code>iterator_traits&lt;I&gt;::iterator_category</code>就是向<code>iterator_traits</code>提问迭代器的类型；</li>
<li><code>display_category(xx_iterator_tag)</code>是重载函数，这里就说明了为什么分类不用整数，而是用对象来表示，因为category不论是什么，往上调用<code>display_category</code>函数自然而然编译器就会找到是哪个，如果是整数，就无法写得这么漂亮；</li>
</ol>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;array&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;list&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;forward_list&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;deque&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iterator&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(random_access_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;random_access_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(bidirectional_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;bidirectional_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(forward_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;bidirectional_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(output_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;output_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(input_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;input_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> I&gt;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(I itr)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">typename</span> iterator_traits&lt;I&gt;::iterator_category cagy;</span><br><span class="line">    <span class="built_in">display_category</span>(cagy);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;\ntest_iterator_category().....\n&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">display_category</span>(array&lt;<span class="keyword">int</span>, <span class="number">10</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(vector&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(list&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(forward_list&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(deque&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line"></span><br><span class="line">    <span class="built_in">display_category</span>(set&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(map&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(multiset&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(multimap&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line"></span><br><span class="line">    <span class="built_in">display_category</span>(unordered_set&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(unordered_map&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(unordered_multiset&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(unordered_multimap&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line"></span><br><span class="line">    <span class="comment">//istream_iterator和ostream_iterator在iterator头文件中</span></span><br><span class="line">    <span class="built_in">display_category</span>(istream_iterator&lt;<span class="keyword">int</span>&gt;());</span><br><span class="line">    <span class="built_in">display_category</span>(ostream_iterator&lt;<span class="keyword">int</span>&gt;(cout, <span class="string">&quot;&quot;</span>));</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">linux实测运行结果</span></span><br><span class="line">test_iterator_category().....</span><br><span class="line">random_access_iterator</span><br><span class="line">random_access_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">random_access_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">bidirectional_iterator</span><br><span class="line">input_iterator</span><br><span class="line">output_iterator</span><br></pre></td></tr></table></figure>
<h3 id="各种容器的iterators的iterator_category的typeid"><a class="markdownIt-Anchor" href="#各种容器的iterators的iterator_category的typeid"></a> 各种容器的<code>iterators</code>的<code>iterator_category</code>的<code>typeid</code></h3>
<p>上面的程序是人为进行了些加工，指定了要打印的字符串，但是通过<code>typeid</code>可以直接打印出<code>iterator_category</code></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181201178.png" alt="image-20211228181201178"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;array&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;list&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;forward_list&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;deque&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_set&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unordered_map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iterator&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;typeinfo&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(random_access_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;random_access_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(bidirectional_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;bidirectional_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(forward_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;bidirectional_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(output_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;output_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(input_iterator_tag)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;input_iterator&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> I&gt;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">display_category</span><span class="params">(I itr)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">typename</span> iterator_traits&lt;I&gt;::iterator_category cagy;</span><br><span class="line">    <span class="built_in">display_category</span>(cagy);</span><br><span class="line"></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;typeid(itr).name() = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">typeid</span></span>(itr).<span class="built_in">name</span>() &lt;&lt; endl &lt;&lt; endl;</span><br><span class="line">    <span class="comment">//The output depends on library implementation</span></span><br><span class="line">    <span class="comment">//The particular representation pointed by the</span></span><br><span class="line">    <span class="comment">//returned values is implementation-defined, 返回值由实现的版本定义</span></span><br><span class="line">    <span class="comment">//and may or may not be different for different types.</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;\ntest_iterator_category().....\n&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">display_category</span>(array&lt;<span class="keyword">int</span>, <span class="number">10</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(vector&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(list&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(forward_list&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(deque&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line"></span><br><span class="line">    <span class="built_in">display_category</span>(set&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(map&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(multiset&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(multimap&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line"></span><br><span class="line">    <span class="built_in">display_category</span>(unordered_set&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(unordered_map&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(unordered_multiset&lt;<span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line">    <span class="built_in">display_category</span>(unordered_multimap&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;::<span class="built_in">iterator</span>());</span><br><span class="line"></span><br><span class="line">    <span class="built_in">display_category</span>(istream_iterator&lt;<span class="keyword">int</span>&gt;());</span><br><span class="line">    <span class="built_in">display_category</span>(ostream_iterator&lt;<span class="keyword">int</span>&gt;(cout, <span class="string">&quot;&quot;</span>));</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>运行结果：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">test_iterator_category().....</span><br><span class="line">random_access_iterator</span><br><span class="line">typeid(itr).name() = Pi </span><br><span class="line"></span><br><span class="line">random_access_iterator</span><br><span class="line">typeid(itr).name() = N9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE </span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = St14_List_iteratorIiE # 编译器在编译的时候会在名称前后添加一些东西</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = St18_Fwd_list_iteratorIiE</span><br><span class="line"></span><br><span class="line">random_access_iterator</span><br><span class="line">typeid(itr).name() = St15_Deque_iteratorIiRiPiE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = St23_Rb_tree_const_iteratorIiE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = St17_Rb_tree_iteratorISt4pairIKiiEE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = St23_Rb_tree_const_iteratorIiE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = St17_Rb_tree_iteratorISt4pairIKiiEE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = NSt8__detail14_Node_iteratorIiLb1ELb0EEE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = NSt8__detail14_Node_iteratorISt4pairIKiiELb0ELb0EEE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = NSt8__detail14_Node_iteratorIiLb1ELb0EEE</span><br><span class="line"></span><br><span class="line">bidirectional_iterator</span><br><span class="line">typeid(itr).name() = NSt8__detail14_Node_iteratorISt4pairIKiiELb0ELb0EEE</span><br><span class="line"></span><br><span class="line">input_iterator</span><br><span class="line">typeid(itr).name() = St16istream_iteratorIicSt11char_traitsIcElE</span><br><span class="line"></span><br><span class="line">output_iterator</span><br><span class="line">typeid(itr).name() = St16ostream_iteratorIicSt11char_traitsIcEE</span><br></pre></td></tr></table></figure>
<h3 id="istream_iterator的iterator_category"><a class="markdownIt-Anchor" href="#istream_iterator的iterator_category"></a> istream_iterator的iterator_category</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181237405.png" alt="image-20211228181237405"></p>
<p>说明：</p>
<ol>
<li>接口必须相同，实现可以不同</li>
<li>G2.9版本的<code>istream_iterator</code>有两个模板参数，G3.3版本有4个模板参数，但是后面两个都有默认值；G4.9版本也是4个模板参数；</li>
<li>各个版本都定义了自己的<code>iterator_category</code>为<code>input_iterator_tag</code>；</li>
</ol>
<h3 id="ostream_iterator的iterator_category"><a class="markdownIt-Anchor" href="#ostream_iterator的iterator_category"></a> ostream_iterator的iterator_category</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181318976.png" alt="image-20211228181318976"></p>
<p>说明：</p>
<ol>
<li>和<code>istream_iterator</code>类似，各个版本都是在定义自己的<code>iterator_category</code>为<code>output_iterator_tag</code>；</li>
</ol>
<h2 id="迭代器分类对算法的影响"><a class="markdownIt-Anchor" href="#迭代器分类对算法的影响"></a> 迭代器分类对算法的影响</h2>
<h3 id="distance算法"><a class="markdownIt-Anchor" href="#distance算法"></a> <code>distance</code>算法</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181355615.png" alt="image-20211228181355615"></p>
<p>说明：</p>
<ol>
<li><code>distance</code>算法是计算两个指针之间的距离：
<ul>
<li>如果是连续空间，可以直接相减，调用<code>__distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)</code>函数；</li>
<li>如果不是连续空间，则将<code>first</code>一直往后走直到和<code>last</code>重合，这个往后走的步数，就是两个迭代器之间的距离，调用的是<code>__distance(InputIterator first, InputIterator last, input_iterator_tag)</code>函数；</li>
</ul>
</li>
<li><code>distance</code>算法的返回值要通过询问<code>iteartor_traits</code>获得<code>difference_type</code>，传入的<code>Iterator</code>的<code>category</code>也要通过询问<code>iterator_traits</code>获得；<code>category()</code>是个临时对象，记住这种写法<code>typename()</code>是创建临时对象；</li>
<li>如果两个迭代器之间有100万个元素，那么这两个<code>__distance</code>函数的效率截然不同；</li>
</ol>
<h3 id="advance算法"><a class="markdownIt-Anchor" href="#advance算法"></a> <code>advance</code>算法</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181418127.png" alt="image-20211228181418127"></p>
<p>说明：</p>
<ol>
<li><code>advance</code>算法，根据<code>iterator_category</code>的不同调用不同的<code>__advance</code>函数；</li>
<li><code>iterator_category(const Iterator&amp;)</code>函数就是将传入的迭代器参数丢给<code>iterator_traits</code>，询问其对应的<code>iterator_category</code>是什么，即如图中的解释：协助取出<code>iterator</code>的<code>category</code>并以此创建一个临时对象；</li>
<li>迭代器的分类之所以没有使用整数来表示，而是使用对象，是因为这些分类之间有继承关系，如果问出来的分类是<code>forward_iterator_tag</code>，代码中并没有专门为其设计的版本，因为<code>forward_iterator_tag</code>是<code>input_iterator_tag</code>的子类，那么就会进入<code>input_iteartor_tag</code>的版本；</li>
</ol>
<h3 id="copy算法"><a class="markdownIt-Anchor" href="#copy算法"></a> <code>copy</code>算法</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181431735.png" alt="image-20211228181431735"></p>
<p>说明：</p>
<ol>
<li><code>copy</code>算法就是复制，需要知道来源端的起点、终点以及目的端的起点；</li>
<li><code>copy</code>中不断地在检查它所接收到的迭代器是不是特属于某种类型而决定是否要做特别的动作来加快速度；
<ul>
<li>如果迭代器<code>first</code>和<code>last</code>是<code>const char*</code>类型，则调用<code>memmove()</code>，直接传到目的端；</li>
<li>如果迭代器是<code>const wchar_t*</code>类型，也是直接做<code>memmove()</code>；</li>
<li>如果迭代器是<code>InputIterator</code>类型，则调用<code>__copy_dispatch()</code>；在<code>__copy_dispatch()</code>函数中又去检查迭代器的类型：
<ul>
<li>如果是指针类型，则调用<code>__copy_t()</code>函数，判断是否有重要的拷贝构造函数，如果有不重要的拷贝构造函数，就调用<code>memmove()</code>函数；如果有重要的拷贝构造函数，就调用<code>__copy_d()</code>函数，用尾减头确定要拷贝的元素个数，减少了循环次数，速度较快；</li>
<li>如果是<code>&lt;InputIterator，InputIterator&gt;</code>类型，调用<code>__copy()</code>函数，并在该函数中继续判断迭代器的类型：
<ul>
<li>如果是<code>InputIterator</code>类型，则从头开始一个个拷贝，直到拷贝到尾，速度很慢；</li>
<li>如果是<code>RandomAccessIterator</code>类型，则调用<code>__copy_d()</code>函数，用尾减头确定要拷贝的元素个数，减少了循环次数，速度较快；</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>图中涉及到的<code>Type Traits</code>，将在第四讲中讲解；</li>
</ol>
<h3 id="destroy算法"><a class="markdownIt-Anchor" href="#destroy算法"></a> <code>destroy</code>算法</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181450241.png" alt="image-20211228181450241"></p>
<p>说明：</p>
<ol>
<li>和前面讲解的算法一样，根据传入的迭代器的类型做不同的操作，以使得速度变快；</li>
<li>如果要销毁的元素的析构函数不重要，则什么都不做；否则，调用析构函数；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181510827.png" alt="image-20211228181510827"></p>
<h3 id="unique_copy算法"><a class="markdownIt-Anchor" href="#unique_copy算法"></a> <code>unique_copy</code>算法</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211228181538549.png" alt="image-20211228181538549"></p>
<h3 id="算法源码中对iterator_category的暗示"><a class="markdownIt-Anchor" href="#算法源码中对iterator_category的暗示"></a> 算法源码中对iterator_category的”暗示“</h3>
<p>算法是模板函数，即可以接受各种类型。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229145848368.png" alt="image-20211229145848368"></p>
<p>说明：</p>
<ol>
<li><code>sort</code>算法的typename命名为<code>RandomAccessIterator</code>就是暗示接受的迭代器为<code>RandomAccessIterator</code>，此处的这个typename可以命名为其他的，之所以命名为当前这个，就是一种”暗示“；</li>
<li><code>distance</code>算法暗示接受的迭代器是<code>InputIterator</code>都可以；</li>
<li><code>find</code>算法暗示接受<code>InputIterator</code>;</li>
<li><code>rotate</code>算法暗示接受<code>ForwardIterator</code>;</li>
<li><code>reverse_copy</code>算法暗示接受<code>BidirectionalIterator</code>；</li>
</ol>
<h2 id="算法源码剖析"><a class="markdownIt-Anchor" href="#算法源码剖析"></a> 算法源码剖析</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229150638951.png" alt="image-20211229150638951"></p>
<p>算法要满足模板函数的类型才是C<ins>标准库提供的算法。<code>qsort</code>和<code>bsearch</code>算法是C中的函数，不是标准库中提供的算法。而<code>count_if</code>、<code>find</code>和<code>sort</code>算法是C</ins>标准库中提供的算法。</p>
<h3 id="算法accumulate"><a class="markdownIt-Anchor" href="#算法accumulate"></a> 算法accumulate</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229150916241.png" alt="image-20211229150916241"></p>
<p>说明：</p>
<ol>
<li>
<p><code>accumulate</code>算法的功能是累计，图上有两个版本：</p>
<ul>
<li>三个参数的情况，进行累加，初值加上每个元素；</li>
<li>四个参数的情况，每次都将初值和元素进行<code>binary_op</code>的操作；</li>
</ul>
</li>
<li>
<p>测试代码：</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span>     <span class="comment">// std::cout</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;functional&gt;</span>   <span class="comment">// std::minus</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;numeric&gt;</span>      <span class="comment">// std::accumulate</span></span></span><br><span class="line"><span class="keyword">namespace</span> jj34</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">myfunc</span> <span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;<span class="keyword">return</span> x+<span class="number">2</span>*y;&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">myclass</span> &#123;</span></span><br><span class="line">	<span class="function"><span class="keyword">int</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;<span class="keyword">return</span> x+<span class="number">3</span>*y;&#125;</span><br><span class="line">&#125; myobj;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_accumulate</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;\ntest_accumulate().......... \n&quot;</span>;	</span><br><span class="line">  <span class="keyword">int</span> init = <span class="number">100</span>;</span><br><span class="line">  <span class="keyword">int</span> nums[] = &#123;<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>&#125;;</span><br><span class="line"></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;using default accumulate: &quot;</span>;</span><br><span class="line">  cout &lt;&lt; <span class="built_in">accumulate</span>(nums,nums+<span class="number">3</span>,init);  <span class="comment">//160 使用指针作为迭代器，且前闭后开</span></span><br><span class="line">  cout &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;using functional&#x27;s minus: &quot;</span>;</span><br><span class="line">  <span class="comment">//minus&lt;int&gt;是C++标准库提供的functor，减法</span></span><br><span class="line">  cout &lt;&lt; <span class="built_in">accumulate</span>(nums, nums+<span class="number">3</span>, init, minus&lt;<span class="keyword">int</span>&gt;()); <span class="comment">//40 </span></span><br><span class="line">  cout &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;using custom function: &quot;</span>;</span><br><span class="line">  <span class="comment">//myfunc就是个函数</span></span><br><span class="line">  cout &lt;&lt; <span class="built_in">accumulate</span>(nums, nums+<span class="number">3</span>, init, myfunc);	<span class="comment">//220 </span></span><br><span class="line">  cout &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;using custom object: &quot;</span>;</span><br><span class="line">  <span class="comment">//myobj是函数对象（function object/functor）/仿函数，是个类或结构体，重载()</span></span><br><span class="line">  cout &lt;&lt; <span class="built_in">accumulate</span>(nums, nums+<span class="number">3</span>, init, myobj);	<span class="comment">//280</span></span><br><span class="line">  cout &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">&#125;															 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h3 id="算法for_each"><a class="markdownIt-Anchor" href="#算法for_each"></a> 算法for_each</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229151933041.png" alt="image-20211229151933041"></p>
<p>说明：</p>
<ol>
<li>
<p><code>for_each</code>算法对<code>first</code>到<code>last</code>范围的每个元素做<code>f</code>操作，参数<code>f</code>可以是任何东西，只要能被<code>()</code>调用起来；</p>
</li>
<li>
<p>测试代码：</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span>     <span class="comment">// std::cout</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span>    <span class="comment">// std::for_each</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span>       <span class="comment">// std::vector</span></span></span><br><span class="line"><span class="keyword">namespace</span> jj35</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">myfunc</span> <span class="params">(<span class="keyword">int</span> i)</span> </span>&#123;  <span class="comment">//function</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&#x27; &#x27;</span> &lt;&lt; i;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">myclass</span> &#123;</span>       <span class="comment">//function object</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">operator</span><span class="params">()</span> <span class="params">(<span class="keyword">int</span> i)</span> </span>&#123; cout &lt;&lt; <span class="string">&#x27; &#x27;</span> &lt;&lt; i; &#125;</span><br><span class="line">&#125; myobj;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_for_each</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;\ntest_for_each().......... \n&quot;</span>;	</span><br><span class="line">	</span><br><span class="line">  vector&lt;<span class="keyword">int</span>&gt; myvec;</span><br><span class="line">  myvec.<span class="built_in">push_back</span>(<span class="number">10</span>);</span><br><span class="line">  myvec.<span class="built_in">push_back</span>(<span class="number">20</span>);</span><br><span class="line">  myvec.<span class="built_in">push_back</span>(<span class="number">30</span>);</span><br><span class="line"></span><br><span class="line">  for_each (myvec.<span class="built_in">begin</span>(), myvec.<span class="built_in">end</span>(), myfunc);</span><br><span class="line">  cout &lt;&lt; endl;		<span class="comment">//output: 10 20 30</span></span><br><span class="line"></span><br><span class="line">  for_each (myvec.<span class="built_in">begin</span>(), myvec.<span class="built_in">end</span>(), myobj);</span><br><span class="line">  cout &lt;&lt; endl;		<span class="comment">//output: 10 20 30</span></span><br><span class="line">  </span><br><span class="line">  <span class="comment">//since C++11, range-based for- statement</span></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">auto</span>&amp; elem : myvec)</span><br><span class="line">       elem += <span class="number">5</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">auto</span> elem : myvec)</span><br><span class="line">       cout &lt;&lt; <span class="string">&#x27; &#x27;</span> &lt;&lt; elem ; 	<span class="comment">//output: 15 25 35</span></span><br><span class="line">&#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure>
</li>
<li>
<p>C++11开始新的<code>for</code>循环形式：</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (decl : coll) &#123;</span><br><span class="line">    statement</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h3 id="算法replacereplace_ifreplace_copy"><a class="markdownIt-Anchor" href="#算法replacereplace_ifreplace_copy"></a> 算法replace，replace_if,replace_copy</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229152431896.png" alt="image-20211229152431896"></p>
<p>说明：</p>
<ol>
<li><code>replace</code>函数的参数：头、尾、旧值、新值；条件是元素值和旧值相同；</li>
<li><code>replace_if</code>函数表示需要给定一个条件，参数：头、尾、条件、新值；符合<code>pred(*first)</code>作为条件；</li>
<li><code>replace_copy</code>函数功能是将旧区间的等于旧值的都以新值的形式放到新区间中；</li>
</ol>
<h3 id="算法countcount_if"><a class="markdownIt-Anchor" href="#算法countcount_if"></a> 算法count，count_if</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160700965.png" alt="image-20211229160700965"></p>
<p>说明：</p>
<ol>
<li>左边是标准库的算法，全局的，泛化的；右边是说明容器中是否有该同名的成员函数；</li>
<li>容器<span style="color:red">不带</span>成员函数<code>count()</code>:
<ul>
<li><code>array</code></li>
<li><code>vector</code></li>
<li><code>list</code></li>
<li><code>forward_list</code></li>
<li><code>deque</code></li>
</ul>
</li>
<li>容器<strong>带有</strong>成员函数<code>count()</code>: 使用的时候就要使用容器中的<code>count</code>，针对这种类型的容器做了特别的处理
<ul>
<li><code>set/multiset</code></li>
<li><code>map/multimap</code></li>
<li><code>unordered_set/unordered_multiset</code></li>
<li><code>unordered_map/unordered_multimap</code></li>
</ul>
</li>
<li>容器<strong>带有</strong>成员函数<code>count()</code>的这8个，是associated container，可以用key找到data，小型的数据库，有严谨的结构，内部使用红黑树或哈希表实现，有自己比较快的计数方式；</li>
</ol>
<h3 id="算法findfind_if"><a class="markdownIt-Anchor" href="#算法findfind_if"></a> 算法find，find_if</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160726888.png" alt="image-20211229160726888"></p>
<p>说明：</p>
<ol>
<li><code>find</code>查找，循序查找；</li>
<li><code>find_if</code>查找符合条件的元素；</li>
<li><code>set/multiset</code>、<code>map/multimap</code>、<code>unordered_set/unordered_multiset</code>和<code>unordered_map/unordered_multimap</code>因为有自己严谨的结构，所以使用这些结构，不需要调用全局的<code>find</code>；</li>
</ol>
<h3 id="算法sort"><a class="markdownIt-Anchor" href="#算法sort"></a> 算法sort</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160747760.png" alt="image-20211229160747760"></p>
<p>说明：</p>
<ol>
<li>
<p><code>set/multiset</code>、<code>map/multimap</code>、<code>unordered_set/unordered_multiset</code>和<code>unordered_map/unordered_multimap</code>不带<code>sort</code>，因为遍历自然就形成了<code>sorted</code>状态;</p>
</li>
<li>
<p>默认的排序方法也是从小到大排序；</p>
</li>
<li>
<p>测试代码:</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span>     <span class="comment">// std::cout</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span>    <span class="comment">// std::sort</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span>       <span class="comment">// std::vector</span></span></span><br><span class="line"><span class="keyword">namespace</span> jj36</span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">myfunc</span> <span class="params">(<span class="keyword">int</span> i,<span class="keyword">int</span> j)</span> </span>&#123; <span class="keyword">return</span> (i&lt;j); &#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">myclass</span> &#123;</span></span><br><span class="line">  <span class="function"><span class="keyword">bool</span> <span class="title">operator</span><span class="params">()</span> <span class="params">(<span class="keyword">int</span> i,<span class="keyword">int</span> j)</span> </span>&#123; <span class="keyword">return</span> (i&lt;j);&#125;</span><br><span class="line">&#125; myobj;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">test_sort</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;	</span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;\ntest_sort().......... \n&quot;</span>;	</span><br><span class="line"></span><br><span class="line">  <span class="keyword">int</span> myints[] = &#123;<span class="number">32</span>,<span class="number">71</span>,<span class="number">12</span>,<span class="number">45</span>,<span class="number">26</span>,<span class="number">80</span>,<span class="number">53</span>,<span class="number">33</span>&#125;;</span><br><span class="line">  <span class="function">vector&lt;<span class="keyword">int</span>&gt; <span class="title">myvec</span><span class="params">(myints, myints+<span class="number">8</span>)</span></span>;          <span class="comment">// 32 71 12 45 26 80 53 33</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// using default comparison (operator &lt;):</span></span><br><span class="line">  <span class="built_in">sort</span>(myvec.<span class="built_in">begin</span>(), myvec.<span class="built_in">begin</span>()+<span class="number">4</span>);         <span class="comment">//(12 32 45 71)26 80 53 33</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// using function as comp</span></span><br><span class="line">  <span class="built_in">sort</span>(myvec.<span class="built_in">begin</span>()+<span class="number">4</span>, myvec.<span class="built_in">end</span>(), myfunc); 	<span class="comment">// 12 32 45 71(26 33 53 80)</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// using object as comp</span></span><br><span class="line">  <span class="built_in">sort</span>(myvec.<span class="built_in">begin</span>(), myvec.<span class="built_in">end</span>(), myobj);      <span class="comment">//(12 26 32 33 45 53 71 80)</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// print out content:</span></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;\nmyvec contains:&quot;</span>;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">auto</span> elem : myvec)		<span class="comment">//C++11 range-based for statement</span></span><br><span class="line">       cout &lt;&lt; <span class="string">&#x27; &#x27;</span> &lt;&lt; elem ; 	<span class="comment">//output: 12 26 32 33 45 53 71 80</span></span><br><span class="line">       </span><br><span class="line">  <span class="comment">// using reverse iterators and default comparison (operator &lt;):</span></span><br><span class="line">  <span class="built_in">sort</span>(myvec.<span class="built_in">rbegin</span>(), myvec.<span class="built_in">rend</span>());     </span><br><span class="line">  </span><br><span class="line">  <span class="comment">// print out content:</span></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;\nmyvec contains:&quot;</span>;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">auto</span> elem : myvec)		<span class="comment">//C++11 range-based for statement</span></span><br><span class="line">       cout &lt;&lt; <span class="string">&#x27; &#x27;</span> &lt;&lt; elem ; 	<span class="comment">//output: 80 71 53 45 33 32 26 12    </span></span><br><span class="line">       </span><br><span class="line">  <span class="comment">// using explicitly default comparison (operator &lt;):</span></span><br><span class="line">  <span class="built_in">sort</span>(myvec.<span class="built_in">begin</span>(), myvec.<span class="built_in">end</span>(), less&lt;<span class="keyword">int</span>&gt;());  </span><br><span class="line">  </span><br><span class="line">  <span class="comment">// print out content:</span></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;\nmyvec contains:&quot;</span>;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">auto</span> elem : myvec)		<span class="comment">//C++11 range-based for statement</span></span><br><span class="line">       cout &lt;&lt; <span class="string">&#x27; &#x27;</span> &lt;&lt; elem ; 	<span class="comment">//output: 12 26 32 33 45 53 71 80   </span></span><br><span class="line">	   </span><br><span class="line">  <span class="comment">// using another comparision criteria (operator &gt;):</span></span><br><span class="line">  <span class="built_in">sort</span>(myvec.<span class="built_in">begin</span>(), myvec.<span class="built_in">end</span>(), greater&lt;<span class="keyword">int</span>&gt;());  </span><br><span class="line">  </span><br><span class="line">  <span class="comment">// print out content:</span></span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;\nmyvec contains:&quot;</span>;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">auto</span> elem : myvec)		<span class="comment">//C++11 range-based for statement</span></span><br><span class="line">       cout &lt;&lt; <span class="string">&#x27; &#x27;</span> &lt;&lt; elem ; 	<span class="comment">//output: 80 71 53 45 33 32 26 12 	        </span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>list</code>和<code>forward_list</code>中带有成员函数<code>sort()</code>，因为全局的<code>sort</code>要求是<code>RandomAccessIterator</code>，可以跳跃，但是<code>list</code>和<code>forward_list</code>容器都不能跳跃；</p>
</li>
</ol>
<h3 id="关于reverse-iteratorrbeginrend"><a class="markdownIt-Anchor" href="#关于reverse-iteratorrbeginrend"></a> 关于reverse iterator，rbegin(),rend()</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160817462.png" alt="image-20211229160817462"></p>
<p>说明：</p>
<ol>
<li>图中的绿色小箭头表示如果对迭代器取值得到的元素；</li>
<li><code>rbegin()</code>对应的就是<code>end()</code>的指针，<code>rend()</code>对应的就是<code>begin()</code>的指针，但是需要改变它们的行为，所以加了一个iterator adapter——<code>reverse_iterator</code>，使得取值的时候和原来的指针取值方式变得不同；</li>
</ol>
<h3 id="算法binary_search"><a class="markdownIt-Anchor" href="#算法binary_search"></a> 算法binary_search</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160848023.png" alt="image-20211229160848023"></p>
<p>说明：</p>
<ol>
<li><code>binary_search</code>算法一定是在排序的序列中使用；</li>
<li><code>binary_search</code>就是通过调用<code>lower_bound</code>函数来完成查找；</li>
<li><code>lower_bound</code>找到的是在不违反排序的情况下，找到的能安插要查找的数的最低点，<code>upper_bound</code>是最高点，即返回的是能安插的位置；</li>
</ol>
<h2 id="仿函数和函数对象"><a class="markdownIt-Anchor" href="#仿函数和函数对象"></a> 仿函数和函数对象</h2>
<h3 id="仿函数functors"><a class="markdownIt-Anchor" href="#仿函数functors"></a> 仿函数functors</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160913555.png" alt="image-20211229160913555"></p>
<p>说明：</p>
<ol>
<li>仿函数只为算法服务；</li>
<li>仿函数就是要模仿函数，必须重载<code>()</code>，图中是标准库提供的三大分类的functor；</li>
<li>之所以要将这些操作设计成函数，是为了将这些动操作传到算法中，所以要写成函数或仿函数；</li>
<li>每个标准库提供的仿函数都继承了<code>binary_function</code>；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160927785.png" alt="image-20211229160927785"></p>
<p>说明：</p>
<ol>
<li><code>identity</code>/<code>select1st</code>/<code>select2nd</code> 是GNU C<ins>独有的，C</ins>标准库的规格里并没有规定必须有这些；</li>
<li>G4.9中这三个仿函数的名称变了，变成了<code>_Identity</code>/<code>_Select1st</code>/<code>_Select2nd</code>;</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229160938732.png" alt="image-20211229160938732"></p>
<p>说明：</p>
<ol>
<li>
<pre class="highlight"><code class="cpp"> <span class="hljs-comment">// using explicitly default comparison (operator &lt;):</span>
 sort(myvec.begin(), myvec.end(), less&lt;<span class="hljs-keyword">int</span>&gt;());  
 &lt;!--code￼<span class="hljs-number">31</span>--&gt;

 使用`greater&lt;<span class="hljs-keyword">int</span>&gt;()`就变成了逆向排序，从大到小进行排序；

</code></pre>
</li>
<li>
<p>此处自己编写的仿函数<code>struct myclass</code>没有继承<code>binary_function</code>，就没有融入STL中，那么未来就没有被改造的机会；如果希望自己写的functor能够和STL的体系结构如何的话，就必须选择”适当者“（<code>unary_function</code>或<code>binary_function</code>)继承。。</p>
</li>
</ol>
<h3 id="仿函数functors的可适配adaptable条件"><a class="markdownIt-Anchor" href="#仿函数functors的可适配adaptable条件"></a> 仿函数functors的可适配（adaptable）条件</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161009970.png" alt="image-20211229161009970"></p>
<p>说明：</p>
<ol>
<li><code>binary_function</code>就是两个操作数的操作（+，-,…)，<code>unary_function</code>就是一个操作数；</li>
<li><code>binary_function</code>和<code>unary_function</code>的相同点是接受模板参数并将参数换了个名称，没有data，没有function，所以它们的大小都是0（理论值，实际上可能是1），如果作为父类，那它的大小一定是0；</li>
<li>STL规定每个Adaptable Function都应挑选<strong>适当者</strong>继承之（因为Function Adapter将会提问）。所谓的&quot;可适配（adaptable）&quot;的意思就是可以被修改、适配或调整。如果你希望你写的functor是适配的，那么就要挑选一个”适当者“继承，因为当你被Adapter改造的时候，Adapter可能会来问这些问题，类似算法问迭代器问题。例如<code>less</code>是两个操作的数的操作，所以它要继承<code>binary_function</code>，这里只是继承了typedef，并没有增加额外的开销（没有数据和方法）。</li>
<li>仿函数如果要可适配的条件是能Adapter回答问题，为了能回答Adapter的问题就必须继承”适当者“；</li>
<li>小结：仿函数就是一个类中重载了<code>()</code>,这样的类创建出来的对象就叫做<mark>函数对象</mark>或者<mark>仿函数</mark>，之所以叫做函数对象，是因为创建出来的对象是一个对象，但是它像一个函数；</li>
</ol>
<h2 id="存在多种adapter"><a class="markdownIt-Anchor" href="#存在多种adapter"></a> 存在多种Adapter</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161026819.png" alt="image-20211229161026819"></p>
<p>说明：</p>
<ol>
<li>根据Adapter需要修饰或改造的东西的名称则将其命名为什么：
<ul>
<li><code>Function Adapters</code>:改造Functor；</li>
<li><code>Iterator Adapters</code>: 改造Iterator；</li>
<li><code>Container Adapters</code>: 改造Container；</li>
</ul>
</li>
<li>所有的Adapter都是用<strong>复合</strong>而非继承的方式来使用所要改造的东西的功能；</li>
<li>回顾：算法不知道容器，能够看到的只有迭代器，而迭代器是由容器提供，所以算法想要知道的一切问题都要通过5种typedef来询问迭代器，所以迭代器必须有这5种type；</li>
<li>Adapter是仿函数和算法之间的桥梁，Function Adapter可能想要知道Functors的一些特性，也是通过问和答来实现的，通过3或2个typedef来询问；</li>
</ol>
<h3 id="容器adapter"><a class="markdownIt-Anchor" href="#容器adapter"></a> 容器Adapter</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161041373.png" alt="image-20211229161041373"></p>
<p>说明：</p>
<ol>
<li><code>stack</code>和<code>queue</code>都内含了一个<code>Sequence</code>,默认是个<code>deque</code>，隐藏了某些<code>deque</code>的操作，这是一种改造，修改了函数名称也是一种改造：
<ul>
<li>stack：<code>push_back</code> -&gt; <code>push</code>; <code>pop_back</code>-&gt;<code>pop</code>;</li>
<li>queue: <code>push_back</code> -&gt; <code>push</code>; <code>pop_front</code>-&gt;<code>pop</code>;</li>
</ul>
</li>
</ol>
<h3 id="函数adapter"><a class="markdownIt-Anchor" href="#函数adapter"></a> 函数Adapter</h3>
<h4 id="函数适配器binder2nd"><a class="markdownIt-Anchor" href="#函数适配器binder2nd"></a> 函数适配器：binder2nd</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161055262.png" alt="image-20211229161055262"></p>
<p>说明：</p>
<ol>
<li>
<p><code>binder2nd</code>类中的<code>typename Operation::second_argument_type value;</code>就是在提问：<code>binder2nd</code>这个Adapter在修饰改造一个动作<code>Operation</code>(如之前的<code>less</code>)，询问<code>Operation</code>的<code>second_argument_type</code>是什么，就是Adapter向Functor提问，Functor要回答；</p>
</li>
<li>
<pre class="highlight"><code class="cpp"> count_if(vi.begin(), vi.end(), not1(bind2nd(less&lt;<span class="hljs-keyword">int</span>&gt;(), <span class="hljs-number">40</span>)));
 <span class="hljs-comment">//bind2nd是将第二个参数绑定为特定值，此处是40</span>
 <span class="hljs-comment">//less&lt;int&gt;()：less&lt;int&gt;是类型，加上()产生了临时对象，并不是调用 要准确区分()是创建对象还是函数调用</span>
 &lt;!--code￼<span class="hljs-number">32</span>--&gt;

</code></pre>
</li>
<li>
<pre class="highlight"><code class="cpp"> <span class="hljs-comment">//binding members:</span>
 MyPair ten_two&#123;<span class="hljs-number">10</span>,<span class="hljs-number">2</span>&#125;; <span class="hljs-comment">//设定对象并给定初值</span>
 
 <span class="hljs-comment">//成员函数其实有个参数：this</span>
 <span class="hljs-keyword">auto</span> bound_memfn = bind(&amp;MyPair::multiply, _1); <span class="hljs-comment">//绑定MyPair的成员函数multiply，_1空闲，占位this参数</span>
 <span class="hljs-built_in">cout</span> &lt;&lt; bound_memfn(ten_two) &lt;&lt; <span class="hljs-string">'\n'</span>; <span class="hljs-comment">//调用的时候指定</span>
 
 <span class="hljs-keyword">auto</span> bound_memdata = bind(&amp;MyPair::a, ten_two); <span class="hljs-comment">//调用的时候绑定了this参数</span>
 <span class="hljs-built_in">cout</span> &lt;&lt; bound_memdata() &lt;&lt; <span class="hljs-string">'\n'</span>; <span class="hljs-comment">//取得a</span>
 
 <span class="hljs-keyword">auto</span> bound_memdata2 = bind(&amp;MyPair::b, _1); <span class="hljs-comment">//调用的时候绑定了this参数</span>
 <span class="hljs-built_in">cout</span> &lt;&lt; bound_memdata2(ten_two) &lt;&lt; <span class="hljs-string">'\n'</span>; <span class="hljs-comment">//取得b</span>
 &lt;!--code￼<span class="hljs-number">33</span>--&gt;

</code></pre>
</li>
</ol>
<h3 id="迭代器adapter"><a class="markdownIt-Anchor" href="#迭代器adapter"></a> 迭代器Adapter</h3>
<h4 id="迭代器适配器reverse_iterator"><a class="markdownIt-Anchor" href="#迭代器适配器reverse_iterator"></a> 迭代器适配器：reverse_iterator</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161148961.png" alt="image-20211229161148961"></p>
<p>说明：</p>
<ol>
<li><code>reverse_iterator</code>的关键就是<code>operator*</code>，对逆向迭代器取值，就是对「对应的正向迭代器」退一位取值；</li>
<li>注意其他的操作，都是和正向迭代器的操作是相反的；</li>
</ol>
<h4 id="迭代器适配器inserter"><a class="markdownIt-Anchor" href="#迭代器适配器inserter"></a> 迭代器适配器：inserter</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161205170.png" alt="image-20211229161205170"></p>
<p>说明：</p>
<ol>
<li><code>copy</code>操作是将源端的数据拷贝到目的端，<code>first</code>和<code>last</code>分别是源端的迭代器的头和尾，<code>result</code>是目的端的起始位置，所以将数据拷贝到目的端的时候，目的端的空间是否足够、是否合法，<code>copy</code>操作是不知道的，所以<code>copy</code>和一般的迭代器的搭配的时候拷贝动作是进行”赋值“，有隐患；</li>
<li>我们希望在要插入的位置自己准备空间，放一个元素则创建一个新的空间，而不是进行”赋值“；而<code>copy</code>中的实现是”赋值“，如何变成我们希望的创建新空间呢？可以使用<code>inserter</code>，将目的端的迭代器改成是插入的动作，<code>insert_iterator</code>中进行了<code>operator=</code>函数的重载，所以使得<code>copy</code>中调用的<code>*result = *first</code>操作变成了调用容器的<code>insert</code>操作，而容器的<code>insert</code>操作就会自己开辟一块空间存放数据；</li>
</ol>
<h3 id="x-adapter"><a class="markdownIt-Anchor" href="#x-adapter"></a> X Adapter</h3>
<p>之所以叫做<code>X Adapter</code>，因为不知道要归到哪一类中。</p>
<h4 id="ostream_iterator"><a class="markdownIt-Anchor" href="#ostream_iterator"></a> ostream_iterator</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161217409.png" alt="image-20211229161217409"></p>
<p>说明：</p>
<ol>
<li><code>std::ostream_iterator&lt;int&gt; out_it(std::cout, &quot;,&quot;);</code> 是将迭代器的第一参数绑定到<code>cout</code>上，即放入的数据都显示到屏幕上；第二参数绑定为字符串，作为分隔符号使用；</li>
<li><code>copy</code>中 <code>*</code>、<code>=</code>、<code>++</code>还有返回时会调用拷贝构造都作用在<code>result</code>上，这四个动作要如何改变，才能使得满足我们的需求——元素打印到屏幕上？</li>
<li><code>ostream_iterator</code> 中通过操作符重载<code>operator=</code>使其能够使用cout输出出来；</li>
<li><code>ostream_iterator</code>是<code>ostream</code>的适配器；</li>
</ol>
<h4 id="istream_iterator"><a class="markdownIt-Anchor" href="#istream_iterator"></a> istream_iterator</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161239736.png" alt="image-20211229161239736"></p>
<p>说明：</p>
<ol>
<li><code>std::istream_iterator&lt;double&gt; eos;</code>调用无参构造函数，<code>std::istream_iterator&lt;double&gt; iit(std::cin);</code> 调用有参构造函数，<code>istream_iterator</code>将<code>cin</code>记录到<code>in_stream</code>中；</li>
<li><code>++iit</code>调用<code>istream_iterator</code>的<code>operator++()</code>函数，读入数据；</li>
<li><code>*iit</code>调用<code>istream_iterator</code>的<code>operator*</code>函数，返回读入的数据；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161256258.png" alt="istream_iterator"></p>
<p>说明：</p>
<ol>
<li><code>iit</code>在创建的时候就已经读入了值，所以<code>*first</code>的时候可以取出值了；<code>while</code>循环中一边读入数据，一边返回数据；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211229161314306.png" alt="image-20211229161314306"></p>
<p>图中是写错一行代码报出的错误信息，所以读源码的意义就体现在这里，看到繁杂的错误信息，要有能力分析它们出现的原因。</p>
<h1 id="第四讲"><a class="markdownIt-Anchor" href="#第四讲"></a> 第四讲</h1>
<h2 id="一个万用的hash-function"><a class="markdownIt-Anchor" href="#一个万用的hash-function"></a> 一个万用的Hash Function</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171153305.png" alt="image-20211231171153305"></p>
<p>说明：</p>
<ol>
<li>代码：</li>
</ol>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;functional&gt;</span></span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Customer</span> &#123;</span></span><br><span class="line">    ...</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//形式1</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CustomerHash</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">std::<span class="keyword">size_t</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="keyword">const</span> Customer&amp; c)</span> <span class="keyword">const</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> ...</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">//第二个模板参数传入的是类型</span></span><br><span class="line">unordered_set&lt;Customer, CustomerHash&gt; custset;</span><br><span class="line"></span><br><span class="line"><span class="comment">//形式2</span></span><br><span class="line"><span class="function"><span class="keyword">size_t</span> <span class="title">customer_hash_func</span><span class="params">(<span class="keyword">const</span> Customer&amp; c)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> ...</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//第二个模板参数为函数类型</span></span><br><span class="line">unordered_set&lt;Customer, <span class="built_in">size_t</span>(*)(<span class="keyword">const</span> Customer&amp;)&gt; <span class="built_in">custset</span>(<span class="number">20</span>, customer_hash_func); </span><br></pre></td></tr></table></figure>
<ol start="2">
<li>哈希函数的具体设计：</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171211012.png" alt="image-20211231171211012"></p>
<ul>
<li>
<p>方案一：因为基本类型都具有自己的hash function，所以想着将Customer中的所有数据拆开为基本类型，然后对各种类型进行hash，最后结果合在一起：</p>
  <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CustomerHash</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">std::<span class="keyword">size_t</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="keyword">const</span> Customer&amp;)</span> <span class="keyword">const</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> std::hash&lt;std::string&gt;()(c.fname) +</span><br><span class="line">            std::hash&lt;std::string&gt;()(c.lname) + </span><br><span class="line">            std::hash&lt;<span class="keyword">long</span>&gt;()(c.no);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>这种方案可以使用，但是太过天真，后期可能会产生很多碰撞💥；</p>
</li>
<li>
<p>方案二：使用<code>variadic templates</code>（可变化的模板）</p>
  <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CustomerHash</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">std::<span class="keyword">size_t</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="keyword">const</span> Customer&amp;)</span> <span class="keyword">const</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">hash_val</span>(c.fname, c.lname, c.no); <span class="comment">//将Customer的数据都放入</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span>... Types&gt; <span class="comment">//接受任意个数的模板参数，语法&quot;typename...&quot;</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">size_t</span> <span class="title">hash_val</span><span class="params">(<span class="keyword">const</span> Types&amp;... args)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">size_t</span> seed = <span class="number">0</span>;</span><br><span class="line">    <span class="built_in">hash_val</span>(seed, args...);</span><br><span class="line">    <span class="keyword">return</span> seed;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span>... Types&gt; <span class="comment">//可以接受任意个数的模板参数</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">hash_val</span><span class="params">(<span class="keyword">size_t</span>&amp; seed, <span class="keyword">const</span> T&amp; val, <span class="keyword">const</span> Types&amp;... args)</span> </span>&#123;</span><br><span class="line">    <span class="built_in">hash_combine</span>(seed, val);</span><br><span class="line">    <span class="built_in">hash_val</span>(seed, args...); <span class="comment">//递归调用本身，拆分参数，每次都取一个参数进行hash_combine，直到取到只有一个元素调用hash_val(size_t&amp;, const T&amp;)函数</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//上面两个函数的区别是第一个实参的类型</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;functional&gt;</span></span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">hash_combine</span><span class="params">(<span class="keyword">size_t</span>&amp; seed, <span class="keyword">const</span> T&amp; val)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//最终获得的seed就是Customer的hash-code</span></span><br><span class="line">    seed ^= std::hash&lt;T&gt;()(val) + x09e3779b9 + (seed &lt;&lt; <span class="number">6</span>) + (seed &gt;&gt; <span class="number">2</span>); </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">hash_val</span><span class="params">(<span class="keyword">size_t</span>&amp; seed, <span class="keyword">const</span> T&amp; val)</span> </span>&#123;</span><br><span class="line">    <span class="built_in">hash_combine</span>(seed,val);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<ol start="3">
<li>上面<code>hash_combine</code>函数中的 <code>x09e3779b9</code> 是黄金比例：</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171224902.png" alt="image-20211231171224902"></p>
<ol start="4">
<li>上文的源代码：</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171237136.png" alt="image-20211231171237136"></p>
<ol start="5">
<li>G4.9版本下的Hash Function使用示例：</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20211231171255402.png" alt="image-20211231171255402"></p>
<ol start="6">
<li>
<p>Hash Function的形式3：以 struct hash 偏特化形式实现 Hash Function</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132010313.png" alt="image-20220101132010313"></p>
</li>
</ol>
<p>针对自定义的类型实现偏特化的Hash function：如下是对<code>MyString</code>类型进行特化的版本</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132045090.png" alt="image-20220101132045090"></p>
<p>G4.9中所有的基本类型都有自己的hash function，G2.9中没有对<code>string</code>类型进行特化。</p>
<h2 id="tuple用例"><a class="markdownIt-Anchor" href="#tuple用例"></a> Tuple用例</h2>
<p>tuple：一堆东西的组合，可以指定任意类型的任意个元素为一个整体结构。</p>
<ul>
<li>tuple使用示例：</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132643551.png" alt="image-20220101132643551"></p>
<p>说明：</p>
<ol>
<li>源码</li>
</ol>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;complex&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;functional&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;string, sizeof = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(string) &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;double, sizeof = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="keyword">double</span>) &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;float, sizeof = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="keyword">float</span>) &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;int, sizeof = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="keyword">int</span>) &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;complex&lt;double&gt;, sizeof = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(complex&lt;<span class="keyword">double</span>&gt;) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//tuples</span></span><br><span class="line">    <span class="comment">//create a four-element tuple</span></span><br><span class="line">    <span class="comment">//- elements are initialized with default value (0 for fundamental types)</span></span><br><span class="line">    tuple&lt;string, <span class="keyword">int</span>, <span class="keyword">int</span>, complex&lt;<span class="keyword">double</span>&gt; &gt; t;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;sizeof = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(t) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//create and initialized a tuple explicitly</span></span><br><span class="line">    <span class="function">tuple&lt;<span class="keyword">int</span>, <span class="keyword">float</span>, string&gt; <span class="title">t1</span><span class="params">(<span class="number">41</span>, <span class="number">6.3</span>, <span class="string">&quot;nico&quot;</span>)</span></span>;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;tuple&lt;int, float, string&gt;, sizeof = &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(t1) &lt;&lt; endl;</span><br><span class="line">    <span class="comment">//iterator over elements: 取出元素</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;t1:&quot;</span> &lt;&lt; get&lt;<span class="number">0</span>&gt;(t1) &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; get&lt;<span class="number">1</span>&gt;(t1) &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; get&lt;<span class="number">2</span>&gt;(t1) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//create tuple with make_tuple()</span></span><br><span class="line">    <span class="keyword">auto</span> t2 = <span class="built_in">make_tuple</span>(<span class="number">22</span>, <span class="number">44</span>, <span class="string">&quot;stacy&quot;</span>); <span class="comment">//编译器会进行实参推导出类型</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//assign second value in t2 to t1</span></span><br><span class="line">    get&lt;<span class="number">1</span>&gt;(t1) = get&lt;<span class="number">1</span>&gt;(t2); </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">//comparison and assignment</span></span><br><span class="line">    <span class="comment">//- include type conversion from tuple&lt;int, int, const char*&gt;</span></span><br><span class="line">    <span class="comment">//to tuple&lt;int, float, string&gt;</span></span><br><span class="line">    <span class="keyword">if</span> (t1 &lt; t2) &#123; <span class="comment">//compares value for value</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;t1 &lt; t2&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;t1 &gt;= t2&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    t1 = t2; <span class="comment">//Ok, assigns value for value</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;t1 : &quot;</span> &lt;&lt; t1 &lt;&lt; endl; <span class="comment">//必须重载操作符重载operator&lt;&lt;</span></span><br><span class="line"></span><br><span class="line">    <span class="function">tuple&lt;<span class="keyword">int</span>, <span class="keyword">float</span>, string&gt; <span class="title">t3</span><span class="params">(<span class="number">77</span>, <span class="number">1.1</span>, <span class="string">&quot;more light&quot;</span>)</span></span>;</span><br><span class="line">    <span class="keyword">int</span> i1;</span><br><span class="line">    <span class="keyword">float</span> f1;</span><br><span class="line">    string s1;</span><br><span class="line">    <span class="built_in">tie</span>(i1, f1, s1) = t3; <span class="comment">//assigns values of t to i, f, and s ，取出t3的成分绑定到各个变量</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">typedef</span> tuple&lt;<span class="keyword">int</span>, <span class="keyword">float</span>, string&gt; TupleType;</span><br><span class="line">    cout &lt;&lt; tuple_size&lt;TupleType&gt;::value &lt;&lt; endl; <span class="comment">//yields 3，有3个成分</span></span><br><span class="line">    tuple_element&lt;<span class="number">1</span>, TupleType&gt;::type f1 = <span class="number">1.0</span>; <span class="comment">//yields float</span></span><br><span class="line">    <span class="keyword">typedef</span> tuple_element&lt;<span class="number">1</span>, TupleType&gt;::type T;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="2">
<li>为什么<code>tuple&lt;stirng, int, int, complex&lt;double&gt;&gt; t;</code> 的<code>sizeof(t)</code> 是32， 而不是28(理论上将tuple中的类型大小加起来)呢？</li>
<li>如下是参数数量可变的模板应用到tuple，variadic templates语法自动把n个参数分解为1和n-1，再把n-1分解为1和n-2，…，不断递归直到没有参数，所以variadic templates一定是有一个主体，有一个终止条件。</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220101132708298.png" alt="image-20220101132708298"></p>
<p>tuple继承了自己（每次成分减少一个），variadic template会自动将其处理为继承的关系，如上图右边所示。当参数为0个的时候，使用特化的版本<code>template&lt;&gt; class tuple&lt;&gt;&#123;&#125;;</code>。子类的大小 = 子类本身的数据 + 父类的数据，那么上面提到的问题2，按照这种想法应该就是28，而不应该是32，这个待思考🤔。图中的<code>tail()</code>函数返回值<code>this</code>本来指的是例子中的这三块（41、6.3和nico），但是经过转型后变成只指向上两块（6.3和nico）。</p>
<h2 id="type-traits"><a class="markdownIt-Anchor" href="#type-traits"></a> type traits</h2>
<ul>
<li>G2.9版本的type traits</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010219672.png" alt="image-20220103010219672"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> __<span class="title">true_type</span> &#123;</span>&#125;;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> __<span class="title">false_type</span> &#123;</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//泛化版本</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">type</span>&gt;</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> __<span class="title">type_traits</span> &#123;</span></span><br><span class="line">	<span class="keyword">typedef</span> __true_type  	this_dummy_member_must_be_first;</span><br><span class="line">    <span class="keyword">typedef</span> __false_type 	has_trivial_default_constructor; <span class="comment">//默认构造函数是否重要，默认情况下是重要的</span></span><br><span class="line">    <span class="keyword">typedef</span> __false_type 	has_trivial_copy_constructor; <span class="comment">//拷贝构造函数是否重要，默认情况下是重要的</span></span><br><span class="line">    <span class="keyword">typedef</span> __false_type 	has_trivial_assignment_operator; <span class="comment">//赋值操作是否重要，默认情况下是重要的</span></span><br><span class="line">    <span class="keyword">typedef</span> __false_type 	has_trivial_destructor; <span class="comment">//析构函数是否重要，默认情况下是重要的</span></span><br><span class="line">    <span class="keyword">typedef</span> __false_type 	is_POD_type; <span class="comment">//Plain Old Data，C中的structure，没有function，只有data</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//特化版本</span></span><br><span class="line"><span class="comment">//如果明确知道上面提问的那些函数不重要，那么就可以为这个泛化版本写特化版本，来说明答案不是默认的答案，而是有自己的答案</span></span><br><span class="line"><span class="comment">//对于整数这种type，所提问的那些函数都不重要</span></span><br><span class="line"><span class="keyword">template</span>&lt;&gt; <span class="class"><span class="keyword">struct</span> __<span class="title">type_traits</span>&lt;</span><span class="keyword">int</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_default_constructor; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_copy_constructor; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_assignment_operator; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_destructor; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	is_POD_type; <span class="comment">//Plain Old Data</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//特化版本</span></span><br><span class="line"><span class="keyword">template</span>&lt;&gt; <span class="class"><span class="keyword">struct</span> __<span class="title">type_traits</span>&lt;</span><span class="keyword">double</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_default_constructor; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_copy_constructor; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_assignment_operator; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	has_trivial_destructor; </span><br><span class="line">    <span class="keyword">typedef</span> __true_type 	is_POD_type; <span class="comment">//Plain Old Data</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//自定义的类型，可以照着这种写法自己实现自定义类型的特化版本，自己判断那些函数是否重要，自己回答</span></span><br><span class="line"><span class="comment">//比如“复数类”，没有指针，只有实部和虚部，可以不用写构造函数和析构函数，因为编译器有默认版本，所以那些函数都是不重要的。</span></span><br><span class="line"></span><br><span class="line">__type_traits&lt;Foo&gt;::has_trivial_destructor  <span class="comment">//算法要通过__type_traits询问Foo：你有不重要的析构函数吗</span></span><br></pre></td></tr></table></figure>
<ul>
<li>C++11版本的type traits</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010252815.png" alt="image-20220103010252815"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010319608.png" alt="image-20220103010319608"></p>
<p>新版本不需要对自己的自定义类型实现特化版本，而且可以询问的东西更多了。</p>
<h3 id="type-traits的测试"><a class="markdownIt-Anchor" href="#type-traits的测试"></a> type traits的测试</h3>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010354017.png" alt="image-20220103010354017"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">//global function template</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">type_traits_output</span><span class="params">(<span class="keyword">const</span> T&amp; x)</span> </span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;\ntype traits for type : &quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">typeid</span></span>(T).<span class="built_in">name</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_void\t&quot;</span> &lt;&lt; is_void&lt;T&gt;::value &lt;&lt; endl; <span class="comment">//结果为true或者false</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_integral\t&quot;</span> &lt;&lt; is_integral&lt;T&gt;::value &lt;&lt; end;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_floating_point\t&quot;</span> &lt;&lt; is_floating_point&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_arithmetic\t&quot;</span> &lt;&lt; is_arithmetic&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_signed\t&quot;</span> &lt;&lt; is_signed&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_unsigned\t&quot;</span> &lt;&lt; is_unsigned&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_const\t&quot;</span> &lt;&lt; is_const&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_volatile\t&quot;</span> &lt;&lt; is_volatile&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_class\t&quot;</span> &lt;&lt; is_class&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_function\t&quot;</span> &lt;&lt; is_function&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_reference\t&quot;</span> &lt;&lt; is_reference&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_lvalue_reference\t&quot;</span> &lt;&lt; is_lvalue_reference&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_rvalue_reference\t&quot;</span> &lt;&lt; is_rvalue_reference::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_pointer\t&quot;</span> &lt;&lt; is_pointer&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_member_pointer\t&quot;</span> &lt;&lt; is_member_pointer&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_member_object_pointer\t&quot;</span> &lt;&lt; is_member_object_pointer&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_member_function\t&quot;</span> &lt;&lt; is_member_function&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_fundamental\t&quot;</span> &lt;&lt; is_fundamental&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_scalar\t&quot;</span> &lt;&lt; is_scalar&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_object\t&quot;</span> &lt;&lt; is_object&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;is_compound\t&quot;</span> &lt;&lt; is_compound&lt;T&gt;::value &lt;&lt; endl;</span><br><span class="line">    ... <span class="comment">//如下的测试结果图中更多</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010420319.png" alt="image-20220103010420319"></p>
<p>说明：</p>
<ol>
<li>以上是将 string 放入 type_traits_output 函数进行测试的结果；</li>
<li>类中如果有指针的时候就需要编写析构函数；当类要被作为基类的时候，需要写虚析构函数，但是因为 string 并不会被作为基类，所以析构函数不需要写成virtual；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010653691.png" alt="image-20220103010653691"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span> &#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> d1, d2;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">type_traits_output</span>(<span class="built_in">Foo</span>());</span><br></pre></td></tr></table></figure>
<p>说明：</p>
<ol>
<li><code>Foo</code> 中没有 function，只有data，所以它是pod type；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010717974.png" alt="image-20220103010717974"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Goo</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">virtual</span> ~Goo &#123; &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> d1, d2;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="built_in">type_traits_output</span>(<span class="built_in">Goo</span>());</span><br></pre></td></tr></table></figure>
<p>说明：</p>
<ol>
<li><code>Goo</code>中有虚析构函数，所以<code>has_virtual_destructor</code>结果是true；</li>
<li><code>is_polymorphic</code>是否为多态，“多态”类是声明或继承了virtual 方法，<code>Goo</code>中声明了 virtual function，所以它是多态的；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103010807126.png" alt="image-20220103010807126"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Zoo</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Zoo</span>(<span class="keyword">int</span> i1, <span class="keyword">int</span> i2): <span class="built_in">d1</span>(i1), <span class="built_in">d2</span>(i2) &#123; &#125; <span class="comment">//构造函数</span></span><br><span class="line">    <span class="built_in">Zoo</span>(<span class="keyword">const</span> Zoo&amp;) = <span class="keyword">delete</span>; <span class="comment">//拷贝构造</span></span><br><span class="line">    <span class="built_in">Zoo</span>(Zoo&amp;&amp;) = <span class="keyword">default</span>; <span class="comment">//move constructor</span></span><br><span class="line">    Zoo&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> Zoo&amp;) = <span class="keyword">default</span>; <span class="comment">//拷贝赋值</span></span><br><span class="line">    Zoo&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> Zoo&amp;&amp;) = <span class="keyword">delete</span>; <span class="comment">//move assignment </span></span><br><span class="line">    <span class="keyword">virtual</span> ~<span class="built_in">Zoo</span>() &#123; &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> d1, d2;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="built_in">type_traits_output</span>(<span class="built_in">Zoo</span>(<span class="number">1</span>, <span class="number">2</span>));</span><br></pre></td></tr></table></figure>
<p>说明：</p>
<ol>
<li>因为自己编写了构造函数，所以没有默认构造函数；</li>
<li>拷贝构造函数被delete了，所以没有拷贝构造函数；</li>
<li>…</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011102123.png" alt="image-20220103011102123"></p>
<p>说明：</p>
<ol>
<li>复数只有实部和虚部，所以不用写虚析构函数，编译器会有默认的，这个析构函数是不重要的；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011209379.png" alt="image-20220103011209379"></p>
<h3 id="type-traits的实现"><a class="markdownIt-Anchor" href="#type-traits的实现"></a> type traits的实现</h3>
<h4 id="is_void"><a class="markdownIt-Anchor" href="#is_void"></a> is_void</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011330517.png" alt="image-20220103011330517"></p>
<p>说明：</p>
<ol>
<li>都是使用“模板”对类型做操作；</li>
<li><code>remove_cv</code>是先将关键字const和volatile拿掉；</li>
<li><code>struct remove_const&lt;_Tp const&gt;</code> 是偏特化，范围的偏特化；</li>
<li><code>is_void</code>模板类先利用<code>remove_cv</code>将<code>const</code>和<code>volatile</code>去除，然后进入<code>__is_void_helper</code>，如果是 <code>void</code>，则返回真，否则返回假；</li>
</ol>
<h4 id="is_integral"><a class="markdownIt-Anchor" href="#is_integral"></a> is_integral</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011400517.png" alt="image-20220103011400517"></p>
<p>说明：</p>
<ol>
<li><code>is_integral</code>判断是否为整数类型；</li>
<li><code>is_integral</code>会先将const和volatile关键字拿掉，然后进入<code>__is_integral_helper</code>中，根据类型不同进入不同的偏特化版本；</li>
</ol>
<h4 id="is_classis_unionis_enum-is_pod"><a class="markdownIt-Anchor" href="#is_classis_unionis_enum-is_pod"></a> is_class，is_union，is_enum, is_pod</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011436556.png" alt="image-20220103011436556"></p>
<p>说明：</p>
<ol>
<li>蓝色的这些没有在C++标准库的源代码中，可能是编译器编译的时候整理出来的结果；</li>
</ol>
<h4 id="is_move_assignable"><a class="markdownIt-Anchor" href="#is_move_assignable"></a> is_move_assignable</h4>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011501814.png" alt="image-20220103011501814"></p>
<p>说明：</p>
<ol>
<li>和上面一样，<code>is_reference</code>已经不在C++标准库源代码中；</li>
<li>type traits就是一个类型萃取机；</li>
</ol>
<h2 id="cout"><a class="markdownIt-Anchor" href="#cout"></a> cout</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011521657.png" alt="image-20220103011521657"></p>
<p>说明：</p>
<ol>
<li><code>cout</code>是个对象，<code>extern</code>表明外界可以使用它；</li>
<li>通过cout输出对象，因为它对不同类型产生的对象进行了重载<code>operator&lt;&lt;</code>，如果没有出现在重载的类型中，就需要自己重载<code>operator&lt;&lt;</code></li>
<li>标准库中对<code>&lt;&lt;</code>的操作符重载：</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011537389.png" alt="image-20220103011537389"></p>
<h2 id="moveable元素对容器速度效能的影响"><a class="markdownIt-Anchor" href="#moveable元素对容器速度效能的影响"></a> moveable元素对容器速度效能的影响</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011559124.png" alt="image-20220103011559124"></p>
<p>说明：</p>
<ol>
<li>
<p>上面的是moveable 元素的测试，300万个元素放入vector中，调用了0次copy constructor，但是调用了7194303次move constructor。花费的时间是8547ms；</p>
</li>
<li>
<p>下面的是non-moveable元素的测试，同样300万个元素，放入vector中，调用了7194303次copy constructor，调用了0次move constructor，花费的时间是14235ms；</p>
</li>
<li>
<p><code>M c11(c1);</code>是拷贝构造；<code>M c12(std::move(c1));</code>是move copy；</p>
</li>
<li>
<p>不同类型的容器调用相同的一份代码测试插入300万个元素：</p>
 <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">long</span> i = <span class="number">0</span>; i &lt; value; ++i) &#123;</span><br><span class="line">    <span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());</span><br><span class="line">    <span class="keyword">auto</span> ite = c1.<span class="built_in">end</span>();</span><br><span class="line">    c1.<span class="built_in">insert</span>(ite, <span class="built_in">V1type</span>(buf));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>vector的特性是当空间不够用的时候，就要2倍增长空间，并且将原来的数据拷贝到新的空间，这个过程会调用拷贝构造或拷贝赋值，因此，多出了很多的构造函数的调用；</p>
</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011615400.png" alt="image-20220103011615400"></p>
<p>说明：</p>
<ol>
<li>不同于vector，list没有扩充或增长的行为，放300万个元素就调用300万次构造函数；</li>
<li>后面的容器也是相同的行为模式</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011629785.png" alt="image-20220103011629785"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011643134.png" alt="image-20220103011643134"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011656143.png" alt="image-20220103011656143"></p>
<h2 id="写一个moveable-class"><a class="markdownIt-Anchor" href="#写一个moveable-class"></a> 写一个moveable class</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011711668.png" alt="image-20220103011711668"></p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011726355.png" alt="image-20220103011726355"></p>
<p>源码：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span>  <span class="comment">//snprintf()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span> <span class="comment">//RAND_MAX</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span> <span class="comment">//strlen(), memcpy()</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> std::cin;</span><br><span class="line"><span class="keyword">using</span> std::cout;</span><br><span class="line"><span class="keyword">using</span> std::string;</span><br><span class="line"></span><br><span class="line"><span class="comment">//以下 MyString 是為了測試 containers with moveable elements 效果.  </span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyString</span> &#123;</span> </span><br><span class="line"><span class="keyword">public</span>: </span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> DCtor;  	<span class="comment">//累計 default-ctor 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> Ctor;  	<span class="comment">//累計 ctor      的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> CCtor;  	<span class="comment">//累計 copy-ctor 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> CAsgn;  	<span class="comment">//累計 copy-asgn 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> MCtor;  	<span class="comment">//累計 move-ctor 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> MAsgn;  	<span class="comment">//累計 move-asgn 的呼叫次數 		    </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> Dtor;	<span class="comment">//累計 dtor 的呼叫次數 </span></span><br><span class="line"><span class="keyword">private</span>:     </span><br><span class="line">  	<span class="keyword">char</span>* _data; </span><br><span class="line">  	<span class="keyword">size_t</span> _len; </span><br><span class="line">  	<span class="keyword">void</span> _init_data(<span class="keyword">const</span> <span class="keyword">char</span> *s) &#123; </span><br><span class="line">    		_data = <span class="keyword">new</span> <span class="keyword">char</span>[_len+<span class="number">1</span>]; </span><br><span class="line">    		<span class="built_in">memcpy</span>(_data, s, _len); </span><br><span class="line">    		_data[_len] = <span class="string">&#x27;\0&#x27;</span>; </span><br><span class="line">  	&#125; </span><br><span class="line"><span class="keyword">public</span>: </span><br><span class="line">	<span class="comment">//default ctor</span></span><br><span class="line">  	<span class="built_in">MyString</span>() : _data(<span class="literal">NULL</span>), _len(<span class="number">0</span>) &#123; ++DCtor;  &#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">//ctor</span></span><br><span class="line">  	<span class="built_in">MyString</span>(<span class="keyword">const</span> <span class="keyword">char</span>* p) : _len(<span class="built_in">strlen</span>(p)) &#123; </span><br><span class="line">  		++Ctor; </span><br><span class="line">    	_init_data(p); </span><br><span class="line">  	&#125; </span><br><span class="line"></span><br><span class="line">	<span class="comment">// copy ctor</span></span><br><span class="line">  	<span class="built_in">MyString</span>(<span class="keyword">const</span> MyString&amp; str) : _len(str._len) &#123; </span><br><span class="line">		++CCtor;  	  </span><br><span class="line">    	_init_data(str._data); 	<span class="comment">//COPY</span></span><br><span class="line">  	&#125; </span><br><span class="line"></span><br><span class="line">	<span class="comment">//move ctor, with &quot;noexcept&quot;， 和copy ctor的区别在于参数有两个&amp;，只是拷贝指针</span></span><br><span class="line">    <span class="built_in">MyString</span>(MyString&amp;&amp; str) <span class="keyword">noexcept</span> : _data(str._data), _len(str._len)  &#123;  </span><br><span class="line">        ++MCtor;    </span><br><span class="line">    	str._len = <span class="number">0</span>; 		</span><br><span class="line">    	str._data = <span class="literal">NULL</span>;  	<span class="comment">//避免 delete (in dtor) </span></span><br><span class="line"> 	&#125;</span><br><span class="line"> </span><br><span class="line"> 	<span class="comment">//copy assignment</span></span><br><span class="line">  	MyString&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> MyString&amp; str) &#123; </span><br><span class="line">    	++CAsgn;  	 </span><br><span class="line">		<span class="keyword">if</span> (<span class="keyword">this</span> != &amp;str) &#123; </span><br><span class="line">    		<span class="keyword">if</span> (_data) <span class="keyword">delete</span> _data;  </span><br><span class="line">      		_len = str._len; </span><br><span class="line">      		_init_data(str._data); 	<span class="comment">//COPY! </span></span><br><span class="line">    	&#125; </span><br><span class="line">    	<span class="keyword">else</span> &#123;</span><br><span class="line">		    <span class="comment">// Self Assignment, Nothing to do.   </span></span><br><span class="line">		&#125;</span><br><span class="line">    	<span class="keyword">return</span> *<span class="keyword">this</span>; </span><br><span class="line">  	&#125; </span><br><span class="line"></span><br><span class="line">	<span class="comment">//move assignment</span></span><br><span class="line">   	MyString&amp; <span class="keyword">operator</span>=(MyString&amp;&amp; str) <span class="keyword">noexcept</span> &#123; 	 </span><br><span class="line">     	++MAsgn;   	</span><br><span class="line">    	<span class="keyword">if</span> (<span class="keyword">this</span> != &amp;str) &#123; </span><br><span class="line">    		<span class="keyword">if</span> (_data) <span class="keyword">delete</span> _data; </span><br><span class="line">      		_len = str._len; </span><br><span class="line">      		_data = str._data;	<span class="comment">//MOVE!</span></span><br><span class="line">      		str._len = <span class="number">0</span>; </span><br><span class="line">      		str._data = <span class="literal">NULL</span>; 	<span class="comment">//避免 deleted in dtor </span></span><br><span class="line">    	&#125; </span><br><span class="line">    	<span class="keyword">return</span> *<span class="keyword">this</span>; </span><br><span class="line"> 	&#125;</span><br><span class="line"> </span><br><span class="line"> 	<span class="comment">//dtor</span></span><br><span class="line">  	<span class="keyword">virtual</span> ~<span class="built_in">MyString</span>() &#123; 	</span><br><span class="line">  	    ++Dtor;	      	  	    </span><br><span class="line">    	<span class="keyword">if</span> (_data) &#123; <span class="comment">//</span></span><br><span class="line">    		<span class="keyword">delete</span> _data; 	</span><br><span class="line">		&#125;</span><br><span class="line">  	&#125;   	</span><br><span class="line">  	</span><br><span class="line">  	<span class="keyword">bool</span> </span><br><span class="line">  	<span class="keyword">operator</span>&lt;(<span class="keyword">const</span> MyString&amp; rhs) <span class="keyword">const</span>	<span class="comment">//為了讓 set 比較大小  </span></span><br><span class="line">  	&#123;</span><br><span class="line">	   <span class="keyword">return</span> std::<span class="built_in">string</span>(<span class="keyword">this</span>-&gt;_data) &lt; std::<span class="built_in">string</span>(rhs._data); 	<span class="comment">//借用事實：string 已能比較大小. </span></span><br><span class="line">	&#125;</span><br><span class="line">  	<span class="keyword">bool</span> </span><br><span class="line">  	<span class="keyword">operator</span>==(<span class="keyword">const</span> MyString&amp; rhs) <span class="keyword">const</span>	<span class="comment">//為了讓 set 判斷相等. </span></span><br><span class="line">  	&#123;</span><br><span class="line">	   <span class="keyword">return</span> std::<span class="built_in">string</span>(<span class="keyword">this</span>-&gt;_data) == std::<span class="built_in">string</span>(rhs._data); 	<span class="comment">//借用事實：string 已能判斷相等. </span></span><br><span class="line">	&#125;	</span><br><span class="line">	</span><br><span class="line">	<span class="function"><span class="keyword">char</span>* <span class="title">get</span><span class="params">()</span> <span class="keyword">const</span> </span>&#123; <span class="keyword">return</span> _data; &#125;</span><br><span class="line">&#125;; </span><br><span class="line"><span class="comment">//在class之外给static数据定义</span></span><br><span class="line"><span class="keyword">size_t</span> MyString::DCtor=<span class="number">0</span>;  	</span><br><span class="line"><span class="keyword">size_t</span> MyString::Ctor=<span class="number">0</span>;  	 </span><br><span class="line"><span class="keyword">size_t</span> MyString::CCtor=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyString::CAsgn=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyString::MCtor=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyString::MAsgn=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyString::Dtor=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> std 	<span class="comment">//必須放在 std 內 </span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">template</span>&lt;&gt; </span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">hash</span>&lt;</span>MyString&gt; 	<span class="comment">//這是為了 unordered containers </span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="function"><span class="keyword">size_t</span> </span></span><br><span class="line"><span class="function">	<span class="title">operator</span><span class="params">()</span><span class="params">(<span class="keyword">const</span> MyString&amp; s)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span></span></span><br><span class="line"><span class="function">	</span>&#123;  <span class="keyword">return</span> hash&lt;string&gt;()(<span class="built_in">string</span>(s.<span class="built_in">get</span>()));  &#125;  </span><br><span class="line">	    <span class="comment">//借用現有的 hash&lt;string&gt; (in ...\include\c++\bits\basic_string.h)</span></span><br><span class="line">&#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011745981.png" alt="image-20220103011745981"></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyStrNoMove</span> &#123;</span> </span><br><span class="line"><span class="keyword">public</span>: </span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> DCtor;  	<span class="comment">//累計 default-ctor 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> Ctor;  	<span class="comment">//累計 ctor      的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> CCtor;  	<span class="comment">//累計 copy-ctor 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> CAsgn;  	<span class="comment">//累計 copy-asgn 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> MCtor;  	<span class="comment">//累計 move-ctor 的呼叫次數 </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> MAsgn;  	<span class="comment">//累計 move-asgn 的呼叫次數 		    </span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">size_t</span> Dtor;	    <span class="comment">//累計 dtor 的呼叫次數 </span></span><br><span class="line"><span class="keyword">private</span>:     </span><br><span class="line">  	<span class="keyword">char</span>* _data; </span><br><span class="line">  	<span class="keyword">size_t</span> _len; </span><br><span class="line">  	<span class="keyword">void</span> _init_data(<span class="keyword">const</span> <span class="keyword">char</span> *s) &#123; </span><br><span class="line">    		_data = <span class="keyword">new</span> <span class="keyword">char</span>[_len+<span class="number">1</span>]; </span><br><span class="line">    		<span class="built_in">memcpy</span>(_data, s, _len); </span><br><span class="line">    		_data[_len] = <span class="string">&#x27;\0&#x27;</span>; </span><br><span class="line">  	&#125; </span><br><span class="line"><span class="keyword">public</span>: </span><br><span class="line">	<span class="comment">//default ctor</span></span><br><span class="line">  	<span class="built_in">MyStrNoMove</span>() : _data(<span class="literal">NULL</span>), _len(<span class="number">0</span>) &#123; 	++DCtor; _init_data(<span class="string">&quot;jjhou&quot;</span>); &#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">//ctor</span></span><br><span class="line">  	<span class="built_in">MyStrNoMove</span>(<span class="keyword">const</span> <span class="keyword">char</span>* p) : _len(<span class="built_in">strlen</span>(p)) &#123; </span><br><span class="line">    	++Ctor;  _init_data(p); </span><br><span class="line">  	&#125; </span><br><span class="line"></span><br><span class="line">	<span class="comment">// copy ctor</span></span><br><span class="line">  	<span class="built_in">MyStrNoMove</span>(<span class="keyword">const</span> MyStrNoMove&amp; str) : _len(str._len) &#123; </span><br><span class="line">		++CCtor;  	 </span><br><span class="line">    	_init_data(str._data); 	<span class="comment">//COPY</span></span><br><span class="line">  	&#125; </span><br><span class="line"></span><br><span class="line"> 	<span class="comment">//copy assignment</span></span><br><span class="line">  	MyStrNoMove&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> MyStrNoMove&amp; str) &#123; </span><br><span class="line">    	++CAsgn;</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (<span class="keyword">this</span> != &amp;str) &#123; </span><br><span class="line">    		<span class="keyword">if</span> (_data) <span class="keyword">delete</span> _data;  </span><br><span class="line">      		_len = str._len; </span><br><span class="line">      		_init_data(str._data); 	<span class="comment">//COPY! </span></span><br><span class="line">    	&#125; </span><br><span class="line">    	<span class="keyword">else</span> &#123;</span><br><span class="line">		    <span class="comment">// Self Assignment, Nothing to do.   </span></span><br><span class="line">		&#125;</span><br><span class="line">    	<span class="keyword">return</span> *<span class="keyword">this</span>; </span><br><span class="line">  	&#125; </span><br><span class="line"></span><br><span class="line"> 	<span class="comment">//dtor</span></span><br><span class="line">  	<span class="keyword">virtual</span> ~<span class="built_in">MyStrNoMove</span>() &#123; 	   </span><br><span class="line">  	    ++Dtor;		  	    </span><br><span class="line">    	<span class="keyword">if</span> (_data) &#123;</span><br><span class="line">    		<span class="keyword">delete</span> _data; 	</span><br><span class="line">		&#125;</span><br><span class="line">  	&#125;   	</span><br><span class="line">  	</span><br><span class="line">  	<span class="keyword">bool</span> 											</span><br><span class="line">  	<span class="keyword">operator</span>&lt;(<span class="keyword">const</span> MyStrNoMove&amp; rhs) <span class="keyword">const</span>		<span class="comment">//為了讓 set 比較大小 </span></span><br><span class="line">  	&#123;</span><br><span class="line">	   <span class="keyword">return</span> <span class="built_in">string</span>(<span class="keyword">this</span>-&gt;_data) &lt; <span class="built_in">string</span>(rhs._data);  <span class="comment">//借用事實：string 已能比較大小. </span></span><br><span class="line">	&#125;  	</span><br><span class="line">	</span><br><span class="line">  	<span class="keyword">bool</span> 											</span><br><span class="line">  	<span class="keyword">operator</span>==(<span class="keyword">const</span> MyStrNoMove&amp; rhs) <span class="keyword">const</span>	<span class="comment">//為了讓 set 判斷相等. </span></span><br><span class="line">  	&#123;</span><br><span class="line">	   <span class="keyword">return</span> <span class="built_in">string</span>(<span class="keyword">this</span>-&gt;_data) == <span class="built_in">string</span>(rhs._data);  <span class="comment">//借用事實：string 已能判斷相等. </span></span><br><span class="line">	&#125; </span><br><span class="line">		</span><br><span class="line">	<span class="function"><span class="keyword">char</span>* <span class="title">get</span><span class="params">()</span> <span class="keyword">const</span> </span>&#123; <span class="keyword">return</span> _data; &#125;	</span><br><span class="line">&#125;; </span><br><span class="line"><span class="keyword">size_t</span> MyStrNoMove::DCtor=<span class="number">0</span>;  	</span><br><span class="line"><span class="keyword">size_t</span> MyStrNoMove::Ctor=<span class="number">0</span>;  </span><br><span class="line"><span class="keyword">size_t</span> MyStrNoMove::CCtor=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyStrNoMove::CAsgn=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyStrNoMove::MCtor=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyStrNoMove::MAsgn=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">size_t</span> MyStrNoMove::Dtor=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> std 	<span class="comment">//必須放在 std 內 </span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">template</span>&lt;&gt; </span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">hash</span>&lt;</span>MyStrNoMove&gt; 	<span class="comment">//這是為了 unordered containers </span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="function"><span class="keyword">size_t</span> </span></span><br><span class="line"><span class="function">	<span class="title">operator</span><span class="params">()</span><span class="params">(<span class="keyword">const</span> MyStrNoMove&amp; s)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span></span></span><br><span class="line"><span class="function">	</span>&#123;  <span class="keyword">return</span> hash&lt;string&gt;()(<span class="built_in">string</span>(s.<span class="built_in">get</span>()));  &#125;  </span><br><span class="line">	   <span class="comment">//借用現有的 hash&lt;string&gt; (in ...\4.9.2\include\c++\bits\basic_string.h)</span></span><br><span class="line">&#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ctime&gt;</span>  <span class="comment">//clock_t, clock()</span></span></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> M, <span class="keyword">typename</span> NM&gt;	</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">test_moveable</span><span class="params">(M c1, NM c2, <span class="keyword">long</span>&amp; value)</span></span></span><br><span class="line"><span class="function"></span>&#123; 	</span><br><span class="line"><span class="keyword">char</span> buf[<span class="number">10</span>];</span><br><span class="line">			</span><br><span class="line">	<span class="comment">//測試 move </span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\n\ntest, with moveable elements&quot;</span> &lt;&lt; endl;			</span><br><span class="line">	<span class="keyword">typedef</span> <span class="keyword">typename</span> iterator_traits&lt;<span class="keyword">typename</span> M::iterator&gt;::value_type  V1type; 	</span><br><span class="line"><span class="keyword">clock_t</span> timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());    		</span><br><span class="line">        <span class="keyword">auto</span> ite = c1.<span class="built_in">end</span>();</span><br><span class="line">        c1.<span class="built_in">insert</span>(ite, <span class="built_in">V1type</span>(buf)); <span class="comment">//所有容器都提供insert， V1type(buf)是个临时对象，右值，所以编译器会调用其move版本	</span></span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;construction, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;size()= &quot;</span> &lt;&lt; c1.<span class="built_in">size</span>() &lt;&lt; endl;		</span><br><span class="line">	<span class="built_in">output_static_data</span>(*(c1.<span class="built_in">begin</span>()));</span><br><span class="line"></span><br><span class="line">	timeStart = <span class="built_in">clock</span>();	</span><br><span class="line"><span class="function">M <span class="title">c11</span><span class="params">(c1)</span></span>;		<span class="comment">//将整个容器拷贝到c11，深拷贝。 c1不是临时对象			</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;copy, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line"></span><br><span class="line">	timeStart = <span class="built_in">clock</span>();	</span><br><span class="line"><span class="function">M <span class="title">c12</span><span class="params">(std::move(c1))</span></span>;	<span class="comment">//move copy，浅拷贝。				</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;move copy, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;</span><br><span class="line">		</span><br><span class="line">	timeStart = <span class="built_in">clock</span>();	</span><br><span class="line">	c11.<span class="built_in">swap</span>(c12);	<span class="comment">//交换					</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;swap, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;		</span><br><span class="line"></span><br><span class="line">	</span><br><span class="line">	</span><br><span class="line">	<span class="comment">//測試 non-moveable 	</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;\n\ntest, with non-moveable elements&quot;</span> &lt;&lt; endl;		</span><br><span class="line">	<span class="keyword">typedef</span> <span class="keyword">typename</span> iterator_traits&lt;<span class="keyword">typename</span> NM::iterator&gt;::value_type  V2type; 				</span><br><span class="line">    timeStart = <span class="built_in">clock</span>();								</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">long</span> i=<span class="number">0</span>; i&lt; value; ++i)</span><br><span class="line">    &#123;</span><br><span class="line">    	<span class="built_in">snprintf</span>(buf, <span class="number">10</span>, <span class="string">&quot;%d&quot;</span>, <span class="built_in">rand</span>());    		</span><br><span class="line">        <span class="keyword">auto</span> ite = c2.<span class="built_in">end</span>();</span><br><span class="line">        c2.<span class="built_in">insert</span>(ite, <span class="built_in">V2type</span>(buf));	</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;construction, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;size()= &quot;</span> &lt;&lt; c2.<span class="built_in">size</span>() &lt;&lt; endl;			</span><br><span class="line">	<span class="built_in">output_static_data</span>(*(c2.<span class="built_in">begin</span>()));</span><br><span class="line"></span><br><span class="line">	timeStart = <span class="built_in">clock</span>();	</span><br><span class="line"><span class="function">NM <span class="title">c21</span><span class="params">(c2)</span></span>;						</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;copy, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;	</span><br><span class="line"></span><br><span class="line">	timeStart = <span class="built_in">clock</span>();	</span><br><span class="line"><span class="function">NM <span class="title">c22</span><span class="params">(std::move(c2))</span></span>;						</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;move copy, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;</span><br><span class="line">		</span><br><span class="line">	timeStart = <span class="built_in">clock</span>();	</span><br><span class="line">	c21.<span class="built_in">swap</span>(c22);						</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;swap, milli-seconds : &quot;</span> &lt;&lt; (<span class="built_in">clock</span>()-timeStart) &lt;&lt; endl;			</span><br><span class="line">&#125;	</span><br></pre></td></tr></table></figure>
<p><code>move</code>之后原来的东西不再使用，才可以选择使用move copy，否则可能会带来隐患：两个指针指向同一块内存。</p>
<h2 id="vector的copy-ctor"><a class="markdownIt-Anchor" href="#vector的copy-ctor"></a> vector的copy ctor</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011759241.png" alt="image-20220103011759241"></p>
<p>说明：</p>
<ol>
<li><code>M c11(c1)</code>这是vector的深拷贝，即如上图的流程；</li>
</ol>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011812065.png" alt="image-20220103011812065"></p>
<p>说明：</p>
<ol>
<li><code>M c12(std::move(c1));</code>这是调用的vector的move ctor，只是将三个指针进行交换，速度很快；</li>
</ol>
<h2 id="stdstring-是否moveable"><a class="markdownIt-Anchor" href="#stdstring-是否moveable"></a> std::string 是否moveable？</h2>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/image-20220103011827090.png" alt="image-20220103011827090"></p>
<p>说明：</p>
<ol>
<li>std::string 的实际类型是<code>basic_string</code>；</li>
<li><code>basic_string</code>中有构造函数，拷贝构造函数，move assign和move constructor，所以std::string是moveable的，可以安心使用；</li>
</ol>


      <div>
        
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>


        
      </div>

    </div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>Maureen
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://maureen-liu.gitee.io/p/ae8b63c8.html" title="C++STL标准库与泛型编程">https://maureen-liu.gitee.io/p/ae8b63c8.html</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/%E4%BE%AF%E6%8D%B7/" rel="tag"># 侯捷</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/p/9725cb23.html" rel="prev" title="C++设计模式">
      <i class="fa fa-chevron-left"></i> C++设计模式
    </a></div>
      <div class="post-nav-item">
    <a href="/p/1cb47e9e.html" rel="next" title="C++面试突击">
      C++面试突击 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          
    <div class="comments" id="valine-comments"></div>

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>
        
      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%89%8D%E8%A8%80"><span class="nav-text"> 前言</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E4%B8%80%E8%AE%B2"><span class="nav-text"> 第一讲</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%AE%A4%E8%AF%86headers-%E7%89%88%E6%9C%AC-%E9%87%8D%E8%A6%81%E8%B5%84%E6%BA%90"><span class="nav-text"> 认识headers、版本、重要资源</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BA%94%E8%AF%A5%E5%85%B7%E5%A4%87%E7%9A%84%E5%9F%BA%E7%A1%80"><span class="nav-text"> 应该具备的基础</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%88%91%E4%BB%AC%E7%9A%84%E7%9B%AE%E6%A0%87"><span class="nav-text"> 我们的目标</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#c-standard-library-vs-standard-template-library"><span class="nav-text"> C++ Standard Library vs. Standard Template Library</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#c%E6%A0%87%E5%87%86%E5%BA%93%E7%89%88%E6%9C%AC"><span class="nav-text"> C++标准库，版本</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%87%8D%E8%A6%81%E7%BD%91%E9%A1%B5"><span class="nav-text"> 重要网页</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B9%A6%E7%B1%8D"><span class="nav-text"> 书籍</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#stl%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E5%9F%BA%E7%A1%80%E4%BB%8B%E7%BB%8D"><span class="nav-text"> STL体系结构基础介绍</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#stl%E5%85%AD%E5%A4%A7%E9%83%A8%E4%BB%B6"><span class="nav-text"> STL六大部件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#stl-%E5%85%AD%E5%A4%A7%E9%83%A8%E4%BB%B6%E5%85%B3%E7%B3%BB"><span class="nav-text"> STL 六大部件关系</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A4%8D%E6%9D%82%E5%BA%A6complexitybig-oh"><span class="nav-text"> 复杂度，Complexity，Big-oh</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%89%8D%E9%97%AD%E5%90%8E%E5%BC%80%E5%8C%BA%E9%97%B4"><span class="nav-text"> “前闭后开”区间</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#range-based-for-statement-since-c11"><span class="nav-text"> range-based for statement (since C++11)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#auto-keyword-since-c11"><span class="nav-text"> auto keyword (since C++11)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8%E7%9A%84%E5%88%86%E7%B1%BB%E4%B8%8E%E5%90%84%E7%A7%8D%E6%B5%8B%E8%AF%95"><span class="nav-text"> 容器的分类与各种测试</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8-%E7%BB%93%E6%9E%84%E4%B8%8E%E5%88%86%E7%B1%BB"><span class="nav-text"> 容器 — 结构与分类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%A5%E4%B8%8B%E6%B5%8B%E8%AF%95%E7%A8%8B%E5%BA%8F%E4%B9%8B%E8%BE%85%E5%8A%A9%E5%87%BD%E6%95%B0"><span class="nav-text"> 以下测试程序之辅助函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8array"><span class="nav-text"> 使用容器array</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8vector"><span class="nav-text"> 使用容器vector</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8list"><span class="nav-text"> 使用容器list</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8forward_list"><span class="nav-text"> 使用容器forward_list</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8slist"><span class="nav-text"> 使用容器slist</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8deque"><span class="nav-text"> 使用容器deque</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8stack"><span class="nav-text"> 使用容器stack</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8queue"><span class="nav-text"> 使用容器queue</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8multiset"><span class="nav-text"> 使用容器multiset</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8multimap"><span class="nav-text"> 使用容器multimap</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8unordered_multiset"><span class="nav-text"> 使用容器unordered_multiset</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8unordered_multimap"><span class="nav-text"> 使用容器unordered_multimap</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8set"><span class="nav-text"> 使用容器set</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8map"><span class="nav-text"> 使用容器map</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8unordered_set"><span class="nav-text"> 使用容器unordered_set</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8unordered_map"><span class="nav-text"> 使用容器unordered_map</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8hash_multiset%E6%B3%A8%E6%84%8F%E6%89%80%E5%9C%A8%E7%9A%84%E5%A4%B4%E6%96%87%E4%BB%B6"><span class="nav-text"> 使用容器hash_multiset（注意所在的头文件）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8hash_multimap%E6%B3%A8%E6%84%8F%E6%89%80%E5%9C%A8%E7%9A%84%E5%A4%B4%E6%96%87%E4%BB%B6"><span class="nav-text"> 使用容器hash_multimap（注意所在的头文件）</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%86%E9%85%8D%E5%99%A8%E7%9A%84%E6%B5%8B%E8%AF%95"><span class="nav-text"> 分配器的测试</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%88%86%E9%85%8D%E5%99%A8allocator"><span class="nav-text"> 使用分配器allocator</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E4%BA%8C%E8%AE%B2"><span class="nav-text"> 第二讲</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BA%94%E5%85%B7%E5%A4%87%E7%9A%84%E5%9F%BA%E7%A1%80"><span class="nav-text"> 应具备的基础</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%BA%90%E4%BB%A3%E7%A0%81%E7%9A%84%E5%88%86%E5%B8%83vc-gcc"><span class="nav-text"> 源代码的分布（VC, GCC)</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A0%87%E5%87%86%E5%BA%93%E7%89%88%E6%9C%ACvisual-c"><span class="nav-text"> 标准库版本，Visual C++</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A0%87%E5%87%86%E5%BA%93%E7%89%88%E6%9C%ACgnu-c"><span class="nav-text"> 标准库版本，GNU C++</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#oop%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B-vs-gp%E6%B3%9B%E5%9E%8B%E7%BC%96%E7%A8%8B"><span class="nav-text"> OOP(面向对象编程) vs. GP(泛型编程)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8A%80%E6%9C%AF%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C%E7%AC%A6%E9%87%8D%E8%BD%BDand%E6%A8%A1%E6%9D%BF%E6%B3%9B%E5%8C%96%E5%85%A8%E7%89%B9%E5%8C%96%E5%81%8F%E7%89%B9%E5%8C%96"><span class="nav-text"> 技术基础：操作符重载and模板（泛化，全特化，偏特化）</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#operator-overloading%E6%93%8D%E4%BD%9C%E7%AC%A6%E9%87%8D%E8%BD%BD"><span class="nav-text"> Operator Overloading，操作符重载</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#class-templates-%E7%B1%BB%E6%A8%A1%E6%9D%BF"><span class="nav-text"> Class Templates, 类模板</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#function-templates%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF"><span class="nav-text"> Function Templates，函数模板</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#member-templates%E6%88%90%E5%91%98%E6%A8%A1%E6%9D%BF"><span class="nav-text"> Member Templates，成员模板</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#specialization%E7%89%B9%E5%8C%96"><span class="nav-text"> Specialization，特化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#partial-specialization%E5%81%8F%E7%89%B9%E5%8C%96"><span class="nav-text"> Partial Specialization，偏特化</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%86%E9%85%8D%E5%99%A8allocators"><span class="nav-text"> 分配器allocators</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%88%E8%B0%88operator-new-%E5%92%8C-malloc"><span class="nav-text"> 先谈operator new() 和 malloc()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#vc6-stl%E5%AF%B9-allocator-%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text"> VC6 STL对 allocator 的使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#bc5-stl%E5%AF%B9allocator%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text"> BC5 STL对allocator的使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g29-stl%E5%AF%B9-allocator%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text"> G2.9 STL对 allocator的使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g49-stl%E5%AF%B9allocator%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text"> G4.9 STL对allocator的使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8%E4%B9%8B%E9%97%B4%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%85%B3%E7%B3%BB%E4%B8%8E%E5%88%86%E7%B1%BB"><span class="nav-text"> 容器之间的实现关系与分类</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8-%E7%BB%93%E6%9E%84%E4%B8%8E%E5%88%86%E7%B1%BB-2"><span class="nav-text"> 容器 — 结构与分类</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2list"><span class="nav-text"> 深度探索list</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#g29%E7%9A%84list"><span class="nav-text"> G2.9的list</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#lists-iterator"><span class="nav-text"> list’s iterator</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g49%E7%9A%84list"><span class="nav-text"> G4.9的list</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8%E7%9A%84%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%E5%92%8Citerator-traits%E7%9A%84%E4%BD%9C%E7%94%A8%E4%B8%8E%E8%AE%BE%E8%AE%A1"><span class="nav-text"> 迭代器的设计原则和Iterator Traits的作用与设计</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#iterator%E9%9C%80%E8%A6%81%E9%81%B5%E5%BE%AA%E7%9A%84%E5%8E%9F%E5%88%99"><span class="nav-text"> Iterator需要遵循的原则</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#iterator-%E5%BF%85%E9%A1%BB%E6%8F%90%E4%BE%9B%E7%9A%84-5-%E7%A7%8D-associated-types"><span class="nav-text"> Iterator 必须提供的 5 种 associated types</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#traits%E7%89%B9%E6%80%A7%E7%89%B9%E5%BE%81%E7%89%B9%E8%B4%A8"><span class="nav-text"> Traits，特性，特征，特质</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%8C%E6%95%B4%E7%9A%84iterator_traits"><span class="nav-text"> 完整的iterator_traits</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%84%E5%BC%8F%E5%90%84%E6%A0%B7%E7%9A%84traits"><span class="nav-text"> 各式各样的Traits</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2vector"><span class="nav-text"> 深度探索vector</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#g29%E7%9A%84vector"><span class="nav-text"> G2.9的vector</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g29%E7%9A%84vectors-iterator"><span class="nav-text"> G2.9的vector’s iterator</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g49%E7%9A%84vector"><span class="nav-text"> G4.9的vector</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g49%E7%9A%84vectors-iterator"><span class="nav-text"> G4.9的vector’s iterator</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2array"><span class="nav-text"> 深度探索array</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#tr1%E7%9A%84array"><span class="nav-text"> TR1的array</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g49%E7%9A%84array"><span class="nav-text"> G4.9的array</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2forward_list"><span class="nav-text"> 深度探索forward_list</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2deque-queue%E5%92%8Cstack"><span class="nav-text"> 深度探索deque、queue和stack</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8deque"><span class="nav-text"> 容器deque</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#g29%E7%9A%84deque"><span class="nav-text"> G2.9的deque</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#dequetinsert"><span class="nav-text"> deque&lt;T&gt;::insert()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#deque%E5%A6%82%E4%BD%95%E6%A8%A1%E6%8B%9F%E8%BF%9E%E7%BB%AD%E7%A9%BA%E9%97%B4"><span class="nav-text"> deque如何模拟连续空间</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#g49%E7%9A%84deque"><span class="nav-text"> G4.9的deque</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8queue"><span class="nav-text"> 容器queue</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8stack"><span class="nav-text"> 容器stack</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#queue%E5%92%8Cstack%E5%85%B3%E4%BA%8E%E5%85%B6-iterator-%E5%92%8C%E5%BA%95%E5%B1%82%E7%BB%93%E6%9E%84"><span class="nav-text"> queue和stack，关于其 iterator 和底层结构</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-stack%E6%88%96queue%E9%83%BD%E4%B8%8D%E5%85%81%E8%AE%B8%E9%81%8D%E5%8E%86%E4%B9%9F%E4%B8%8D%E6%8F%90%E4%BE%9Biterator"><span class="nav-text"> 1、stack或queue都不允许遍历，也不提供iterator</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-queue%E4%B8%8D%E5%8F%AF%E9%80%89%E6%8B%A9vector%E4%BD%9C%E4%B8%BA%E5%BA%95%E5%B1%82%E7%BB%93%E6%9E%84stack%E5%8F%AF%E9%80%89%E6%8B%A9vector%E4%BD%9C%E4%B8%BA%E5%BA%95%E5%B1%82%E7%BB%93%E6%9E%84"><span class="nav-text"> 2、queue不可选择vector作为底层结构，stack可选择vector作为底层结构</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-stack%E5%92%8Cqueue%E9%83%BD%E4%B8%8D%E5%8F%AF%E9%80%89%E6%8B%A9set%E6%88%96map%E4%BD%9C%E4%B8%BA%E5%BA%95%E5%B1%82%E7%BB%93%E6%9E%84"><span class="nav-text"> 3、stack和queue都不可选择set或map作为底层结构</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2rb_tree"><span class="nav-text"> 深度探索RB_tree</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BA%A2%E9%BB%91%E6%A0%91%E7%AE%80%E4%BB%8B"><span class="nav-text"> 红黑树简介</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g29-%E5%AE%B9%E5%99%A8rb_tree"><span class="nav-text"> G2.9 容器rb_tree</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8rb_tree"><span class="nav-text"> 使用容器rb_tree</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#g49-%E5%AE%B9%E5%99%A8_rb_tree"><span class="nav-text"> G4.9 容器_Rb_tree</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8_rb_tree"><span class="nav-text"> 使用容器_Rb_tree</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2setmultiset"><span class="nav-text"> 深度探索set，multiset</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8set"><span class="nav-text"> 容器set</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#vc6-%E5%AE%B9%E5%99%A8set"><span class="nav-text"> VC6 容器set</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8multiset-2"><span class="nav-text"> 使用容器multiset</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2mapmultimap"><span class="nav-text"> 深度探索map，multimap</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#g29-%E7%9A%84%E5%AE%B9%E5%99%A8map"><span class="nav-text"> G2.9 的容器map</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#vc6-%E7%9A%84%E5%AE%B9%E5%99%A8map"><span class="nav-text"> VC6 的容器map</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8multimap-2"><span class="nav-text"> 使用容器multimap</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8map%E7%8B%AC%E7%89%B9%E7%9A%84operator"><span class="nav-text"> 容器map，独特的operator[]</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%AE%B9%E5%99%A8map-2"><span class="nav-text"> 使用容器map</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2hashtable"><span class="nav-text"> 深度探索hashtable</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#g29-hashtable%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text"> G2.9 hashtable的使用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#g49-hashtable%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text"> G4.9 hashtable的使用</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#unorder%E5%AE%B9%E5%99%A8%E6%A6%82%E5%BF%B5"><span class="nav-text"> unorder容器概念</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E4%B8%89%E8%AE%B2"><span class="nav-text"> 第三讲</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%AE%97%E6%B3%95%E7%9A%84%E5%BD%A2%E5%BC%8F"><span class="nav-text"> 算法的形式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8%E7%9A%84%E5%88%86%E7%B1%BB"><span class="nav-text"> 迭代器的分类</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%84%E7%A7%8D%E5%AE%B9%E5%99%A8%E7%9A%84iterators%E7%9A%84iterator_category"><span class="nav-text"> 各种容器的iterators的iterator_category</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%84%E7%A7%8D%E5%AE%B9%E5%99%A8%E7%9A%84iterators%E7%9A%84iterator_category%E7%9A%84typeid"><span class="nav-text"> 各种容器的iterators的iterator_category的typeid</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#istream_iterator%E7%9A%84iterator_category"><span class="nav-text"> istream_iterator的iterator_category</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ostream_iterator%E7%9A%84iterator_category"><span class="nav-text"> ostream_iterator的iterator_category</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%88%86%E7%B1%BB%E5%AF%B9%E7%AE%97%E6%B3%95%E7%9A%84%E5%BD%B1%E5%93%8D"><span class="nav-text"> 迭代器分类对算法的影响</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#distance%E7%AE%97%E6%B3%95"><span class="nav-text"> distance算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#advance%E7%AE%97%E6%B3%95"><span class="nav-text"> advance算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#copy%E7%AE%97%E6%B3%95"><span class="nav-text"> copy算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#destroy%E7%AE%97%E6%B3%95"><span class="nav-text"> destroy算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#unique_copy%E7%AE%97%E6%B3%95"><span class="nav-text"> unique_copy算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81%E4%B8%AD%E5%AF%B9iterator_category%E7%9A%84%E6%9A%97%E7%A4%BA"><span class="nav-text"> 算法源码中对iterator_category的”暗示“</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81%E5%89%96%E6%9E%90"><span class="nav-text"> 算法源码剖析</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95accumulate"><span class="nav-text"> 算法accumulate</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95for_each"><span class="nav-text"> 算法for_each</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95replacereplace_ifreplace_copy"><span class="nav-text"> 算法replace，replace_if,replace_copy</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95countcount_if"><span class="nav-text"> 算法count，count_if</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95findfind_if"><span class="nav-text"> 算法find，find_if</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95sort"><span class="nav-text"> 算法sort</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B3%E4%BA%8Ereverse-iteratorrbeginrend"><span class="nav-text"> 关于reverse iterator，rbegin(),rend()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%B3%95binary_search"><span class="nav-text"> 算法binary_search</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BB%BF%E5%87%BD%E6%95%B0%E5%92%8C%E5%87%BD%E6%95%B0%E5%AF%B9%E8%B1%A1"><span class="nav-text"> 仿函数和函数对象</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%BF%E5%87%BD%E6%95%B0functors"><span class="nav-text"> 仿函数functors</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%BF%E5%87%BD%E6%95%B0functors%E7%9A%84%E5%8F%AF%E9%80%82%E9%85%8Dadaptable%E6%9D%A1%E4%BB%B6"><span class="nav-text"> 仿函数functors的可适配（adaptable）条件</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AD%98%E5%9C%A8%E5%A4%9A%E7%A7%8Dadapter"><span class="nav-text"> 存在多种Adapter</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8adapter"><span class="nav-text"> 容器Adapter</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%87%BD%E6%95%B0adapter"><span class="nav-text"> 函数Adapter</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E9%80%82%E9%85%8D%E5%99%A8binder2nd"><span class="nav-text"> 函数适配器：binder2nd</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8adapter"><span class="nav-text"> 迭代器Adapter</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8%E9%80%82%E9%85%8D%E5%99%A8reverse_iterator"><span class="nav-text"> 迭代器适配器：reverse_iterator</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8%E9%80%82%E9%85%8D%E5%99%A8inserter"><span class="nav-text"> 迭代器适配器：inserter</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#x-adapter"><span class="nav-text"> X Adapter</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#ostream_iterator"><span class="nav-text"> ostream_iterator</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#istream_iterator"><span class="nav-text"> istream_iterator</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E5%9B%9B%E8%AE%B2"><span class="nav-text"> 第四讲</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%80%E4%B8%AA%E4%B8%87%E7%94%A8%E7%9A%84hash-function"><span class="nav-text"> 一个万用的Hash Function</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#tuple%E7%94%A8%E4%BE%8B"><span class="nav-text"> Tuple用例</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#type-traits"><span class="nav-text"> type traits</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#type-traits%E7%9A%84%E6%B5%8B%E8%AF%95"><span class="nav-text"> type traits的测试</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#type-traits%E7%9A%84%E5%AE%9E%E7%8E%B0"><span class="nav-text"> type traits的实现</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#is_void"><span class="nav-text"> is_void</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#is_integral"><span class="nav-text"> is_integral</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#is_classis_unionis_enum-is_pod"><span class="nav-text"> is_class，is_union，is_enum, is_pod</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#is_move_assignable"><span class="nav-text"> is_move_assignable</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#cout"><span class="nav-text"> cout</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#moveable%E5%85%83%E7%B4%A0%E5%AF%B9%E5%AE%B9%E5%99%A8%E9%80%9F%E5%BA%A6%E6%95%88%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D"><span class="nav-text"> moveable元素对容器速度效能的影响</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%99%E4%B8%80%E4%B8%AAmoveable-class"><span class="nav-text"> 写一个moveable class</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#vector%E7%9A%84copy-ctor"><span class="nav-text"> vector的copy ctor</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#stdstring-%E6%98%AF%E5%90%A6moveable"><span class="nav-text"> std::string 是否moveable？</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->
     
      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Maureen"
      src="/images/stan.jpeg">
  <p class="site-author-name" itemprop="name">Maureen</p>
  <div class="site-description" itemprop="description">心之所向，素履以往</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">7</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">2</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/maureenLiu" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;maureenLiu" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://blog.csdn.net/u011386173?spm=1000.2115.3001.5343" title="CSDN → https:&#x2F;&#x2F;blog.csdn.net&#x2F;u011386173?spm&#x3D;1000.2115.3001.5343" rel="noopener" target="_blank"><i class="crosshairs fa-fw"></i>CSDN</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:maureen@qq.com" title="E-Mail → mailto:maureen@qq.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

        <div id="music163player"> 
            <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=1475596788&auto=1&height=66"></iframe> 
        </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2021 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Maureen</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    <span title="站点总字数">307k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">4:39</span>
</div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : false,
      appId      : '7A7ruXkEvS4VKjoTaajLunbw-9Nh9j0Va',
      appKey     : 'E4svxhhfVsrC9eCyM8YfT8uq',
      placeholder: "Just go go",
      avatar     : 'mm',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : false,
      lang       : 'zh-cn' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>

<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/clicklove.js"></script>
